2011-10-11 1 views
5

私はBIGINTに変更したいINT列の主キー列を持っています。私たちのテスト環境と運用環境はMySQLを使用していますが、単体テストでは埋め込みH2データベースを使用しています。Liquibase:H2データベースのmodifyDataTypeリファクタリングを使用してINTオートインクリメント列をBIGINTに変更します。

私は、次のLiquiBaseをリファクタリング作成しました:

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

リファクタリング作品を、私は休止状態を使用してデータベースにオブジェクトを永続化しようとすると、私は次のエラーメッセージ(私はエラーを包みましたを取得しますメッセージ):

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

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] 

MyEventクラスコードに次のHibernateのマッピングを定義しているAbstractBaseEventから継承します

いくつかのポイント:

  • LiquiBaseをのデータ型
  • バージョンのリファクタリングが、これは、MySQLとの作品​​かどうかは、まだテストされていない2.0.1
  • である前に、Hibernateマッピングの作品

答えて

6

私がテストした(休止状態3.6.2.Final、H2 1.3.160、方言:org.hibernate.dialect.H2Dialect)は、あなたのケースで何が起こっているのか:

  • はAUTOとデータ型があるGenerationTypeがされた場合INT、実際の生成 タイプはSEQUENCEです。
  • GenerationTypeがAUTOでデータ型がBIGINTの場合、実際の 世代型はIDENTITYです。結果として、id-fieldが がID BIGINT PRIMARY KEYとして定義され、ID BIGINT ID として定義されていない場合、これは失敗します(H2でPRIMARY KEYを追加すると重複します)。
  • 何ができるか

あなたは、実際の世代型をしたい場合は以前のように、配列であると、その後、

@GeneratedValue(strategy = GenerationType.SEQUENCE) 

が動作しているようです。いずれにしても、documentationのタイプに従うと、シーケンス自体に変更は必要ありません。実際には何も変わらず、どちらの方法でシーケンスが生成されるのかは明らかですので、このようにします。

他の可能性は、既存の値がある可能性があるため、startValueでIDENTITYとして列を定義し、かつGenerationType.AUTOを以前と同じように使用することです。

+0

非常に良い分析です - ありがとうございます。私がSEQUENCEを使って見る唯一の問題は、MySQLがシーケンスをサポートしていないことです。 1つのオプションは、別のケースで使用しているシーケンステーブルを使用することです。 – tronda

+0

良いアイデア - とにかくテーブルを使用するのが最もポータブルです。 –

+0

移植性が懸念される場合は、基本的に疑問はありません: '@ TableGenerator'を使用する必要があります。 –

1

私は最初だけで、Hibernateは列から変な値を取得してすべての問題を除外するために(IDENTITYのような)特定のものにあなたの@GenerationTypeを変更します。またはそれをすべて削除します。

あなたのリファクタリングはうまく見えますが、明らかな問題はありません。

H2とLiquibaseは、引用符で囲まれた識別子に関してはよく一緒に演奏されません。 LiquibaseのH2データベースクラスはいくつかを引用し、他のものを引用しません。たぶん大文字小文字の変換はあなたを台無しにしている?

プリミティブ型が0ときのEclipseLinkは時々問題がある(!)、それは時々nullまたは初期化されていないような値を扱いますが、私の知る限りでは、Hibernateはこの制限を受けないからです。

これは実際の回答ではありませんが、うまくいけば正しい方向を指すようにしてください。

関連する問題