2011-10-11 8 views
5

Tengo una columna de clave principal que es una columna INT que me gustaría cambiar a BIGINT. Nuestro entorno de prueba y producción utiliza MySQL, pero para las pruebas unitarias utilizamos la base de datos H2 incorporada.Liquibase: Cambie una columna de autoincrement INT a BIGINT utilizando modifyDataType refactoring con base de datos H2

He creado la siguiente refactorización Liquibase:

... 
<changeSet id="1" author="trond"> 
    <modifyDataType tableName="event" columnName="id" newDataType="BIGINT" /> 
    <rollback> 
     <modifyDataType tableName="event" columnName="id" newDataType="INT" /> 
    </rollback> 
</changeSet> 
... 

Las obras de refactorización, pero cuando trato de persistir un objeto a la base de datos usando Hibernate, me sale el siguiente mensaje de error (me he envuelto el error mensaje):

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] 

la clase MyEvent hereda de una AbstractBaseEvent que ha definido el siguiente mapeo de Hibernate en el código:

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private long id; 

Unos pocos puntos:

  • El mapeo de Hibernate funciona antes de la refactorización del tipo de datos
  • Versión 2.0.1 de Liquibase es
  • Independientemente de si esto funciona con MySQL todavía no se ha probado

Respuesta

6

Probé (Hibernate 3.6.2.Final, H2 1.3.160, dialecto: org.hibernate.dialect.H2Dialect) lo que está sucediendo en su caso:

  • Cuando se GenerationType AUTO y tipo de datos es INT, generación real tipo es SECUENCIA.
  • Cuando GenerationType es AUTO y el tipo de datos es BIGINT, el tipo de generación real es IDENTIDAD. Como resultado, esto fallará, si id-field es definido como ID BIGINT PRIMARY KEY y no como ID BIGINT IDENTITY (la adición de PRIMARY KEY aquí con H2 sería redundante).

Lo que puede hacer:

Si desea tipo de generación real de ser SECUENCIA, como antes, a continuación,

@GeneratedValue(strategy = GenerationType.SEQUENCE) 

parece funcionar. No se necesitan cambios para la secuencia en sí, porque según documentation el tipo es BIGINT de todos modos. Lo haría de esta manera, porque entonces nada realmente cambia y está claro qué camino se genera

Otra posibilidad es definir la columna como IDENTIDAD con startValue (debido a posibles valores existentes) y usar GenerationType.AUTO como antes.

+0

Muy buen análisis, gracias. El único problema que veo con el uso de SEQUENCE es que MySQL no admite secuencias. Una opción puede ser usar una tabla de secuencia que hemos utilizado en otro caso. – tronda

+0

Buena idea: utilizar la tabla es la más portátil de todos modos. –

+0

Si la portabilidad es su preocupación, básicamente no hay duda: debe usar '@ TableGenerator'. –

1

me gustaría cambiar su primera @GenerationType a algo específico (como IDENTITY) sólo para descartar cualquier problema con Hibernate conseguir valores extraños a partir de una secuencia. O eliminarlo por completo.

Su refactorización se ve bien, y no puedo ver ningún problema obvio.

H2 y Liquibase a menudo no juegan muy bien cuando se trata de identificadores entre comillas; la clase de base de datos H2 en Liquibase cita algunas y no cita otras. ¿Tal vez la conversión de casos te está jodiendo?

EclipseLink a veces tiene problemas cuando un tipo primitivo es 0 (!), Ya que a veces va a tratar un valor como null o no inicializado, pero a mi conocimiento de hibernación no sufre de esta limitación.

Esto no es realmente una respuesta, lo sé, pero con suerte debería hacerlo apuntar en la dirección correcta.

Cuestiones relacionadas