Hibernate Liquibase:使用H2数据库的modifyDataType重构将INT自动增量列更改为BIGINT

Hibernate Liquibase:使用H2数据库的modifyDataType重构将INT自动增量列更改为BIGINT,hibernate,types,refactoring,h2,liquibase,Hibernate,Types,Refactoring,H2,Liquibase,我有一个主键列,它是一个INT列,我想把它改成BIGINT。我们的测试和生产环境使用MySQL,但对于单元测试,我们使用嵌入式H2数据库 我创建了以下Liquibase重构: 。。。 ... 重构工作正常,但当我尝试使用Hibernate将对象持久化到数据库时,会收到以下错误消息(我已经包装了错误消息): MyEvent类继承自AbstractBaseEvent,后者在代码中定义了以下Hibernate映射: @Id @GeneratedValue(策略=GenerationType.AUTO

我有一个主键列,它是一个INT列,我想把它改成BIGINT。我们的测试和生产环境使用MySQL,但对于单元测试,我们使用嵌入式H2数据库

我创建了以下Liquibase重构:

。。。
...
重构工作正常,但当我尝试使用Hibernate将对象持久化到数据库时,会收到以下错误消息(我已经包装了错误消息):

MyEvent类继承自AbstractBaseEvent,后者在代码中定义了以下Hibernate映射:

@Id
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
有几点:

  • hibernate映射在重构数据类型之前工作
  • Liquibase的版本是2.0.1
  • 这是否适用于MySQL还没有测试过

我会首先将您的
@GenerationType
更改为特定的内容(如
标识
),以排除Hibernate从序列中获取奇怪值的任何问题。或者将其全部移除

你的重构看起来很好,我看不到任何明显的问题

H2和Liquibase在引用标识符时常常不能很好地配合;Liquibase中的H2数据库类引用了一些,而没有引用其他。也许案例转换把你搞砸了

EclipseLink有时在原语类型为
0
(!)时会出现问题,因为它有时会将此类值视为
null
或未初始化,但据我所知,Hibernate不受此限制

我知道,这不是一个真正的答案,但希望能为您指明正确的方向。

我测试过(Hibernate 3.6.2.Final,H2 1.3.160,方言:org.Hibernate.dialogue.h2dialogue)您的情况:

  • 当GenerationType为AUTO且数据类型为INT时,实际生成 类型是序列
  • 当GenerationType为AUTO且数据类型为BIGINT时,实际 生成类型是标识。因此,如果id字段为,则此操作将失败 定义为ID BIGINT主键,而不是ID BIGINT标识 (在此处添加带有H2的主键将是多余的)
您可以做什么:

如果您希望实际的生成类型像以前一样是序列,那么

@GeneratedValue(strategy = GenerationType.SEQUENCE)
似乎有效。序列本身不需要任何更改,因为无论如何,相应的类型都是BIGINT。我会这样做,因为那个么并没有什么真正的改变,很清楚序列是以哪种方式生成的


另一种可能是将列定义为具有startValue的标识(因为可能存在值),并像以前一样使用GenerationType.AUTO

这是一个老问题,公认的答案有很好的分析 但我遇到了同样的问题,花了3个小时找到了真正的问题和解决方案,所以值得把它留在这里供将来参考

所以真正的问题是关于液化的问题 此声明


正在生成这个 更改查询

ALTER TABLE event ALTER COLUMN id BIGINT

从id列中删除默认序列值

因此,当您尝试插入新行时,id为null,因此会引发sql错误

不幸的是,ALTER column的行为因数据库供应商而异,因此最好的解决方案可能是为测试(H2)和生产(mysql)创建不同的迁移变更日志

在H2上,您可以在modifyDataType更改后再次使id自动递增



非常好的分析-谢谢。使用SEQUENCE的唯一问题是MySQL不支持序列。一种选择是使用我们在另一种情况下使用过的序列表。好主意-无论如何,使用表是最可移植的。如果您关心可移植性,那么基本上没有问题:您必须使用
@TableGenerator
@GeneratedValue(strategy = GenerationType.SEQUENCE)