Hibernate Liquibase:使用H2数据库的modifyDataType重构将INT自动增量列更改为BIGINT
我有一个主键列,它是一个INT列,我想把它改成BIGINT。我们的测试和生产环境使用MySQL,但对于单元测试,我们使用嵌入式H2数据库 我创建了以下Liquibase重构: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
。。。
...
重构工作正常,但当我尝试使用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)