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

tro*_*nda 5 refactoring types hibernate h2 liquibase

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

我创建了以下Liquibase重构:

...
<changeSet id="1" author="trond">
    <modifyDataType tableName="event" columnName="id" newDataType="BIGINT" />
    <rollback>
        <modifyDataType tableName="event" columnName="id" newDataType="INT" />
    </rollback>
</changeSet>
...
Run Code Online (Sandbox Code Playgroud)

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

ERROR org.hibernate.util.JDBCExceptionReporter [main]: NULL not allowed for column "ID"; 
    SQL statement: insert into event (id, eventtime, guid, meta, objectguid, originatorid, subtype, type) values (null, ?, ?, ?, ?, ?, ?, '0') [90006-140]

JDBC exception on Hibernate data access: 
    SQLException for SQL [insert into event (id, eventtime, guid, meta, objectguid, originatorid, subtype, type) values (null, ?, ?, ?, ?, ?, ?, '0')]; 
    SQL state [90006]; error code [90006]; could not insert: [event.MyEvent]; 
    nested exception is org.hibernate.exception.GenericJDBCException: could not insert: [event.MyEvent]
Run Code Online (Sandbox Code Playgroud)

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

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
Run Code Online (Sandbox Code Playgroud)

几点:

  • hibernate映射在重构数据类型之前有效
  • Liquibase的版本是2.0.1
  • 这是否适用于MySQL尚未经过测试

Mik*_*unu 6

我测试了(Hibernate 3.6.2.Final,H2 1.3.160,方言:org.hibernate.dialect.H2Dialect)你的案例中发生了什么:

  • 当GenerationType为AUTO且数据类型为INT时,实际生成类型为SEQUENCE.
  • 当GenerationType为AUTO且数据类型为BIGINT时,实际生成类型为IDENTITY.因此,如果id-field被定义为ID BIGINT PRIMARY KEY而不是ID BIGINT IDENTITY,那么这将失败(在这里用H2添加PRIMARY KEY将是多余的).

你可以做什么:

如果你想要实际的生成类型是SEQUENCE,那么就像以前一样

@GeneratedValue(strategy = GenerationType.SEQUENCE)
Run Code Online (Sandbox Code Playgroud)

似乎工作.序列本身不需要更改,因为无论如何,根据文档类型是BIGINT.我会这样做,因为那时没有什么真正改变,并且很清楚生成哪种方式的序列

其他可能性是使用startValue将列定义为IDENTITY(因为可能存在的值),并像以前一样使用GenerationType.AUTO.