次のような主キー/ ID フィールドを持つエンティティがあります。
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
これはうまくいきます。私はEclipseLinkを使用してDDLスキーマを作成していますが、列は次のように正しく作成されています:
`id` bigint(20) NOT NULL AUTO_INCREMENT
ただし、PK を自分で指定したいエンティティがいくつかあります (これは、古いデータベースから構築中の新しいデータベースにデータを転送する小さなアプリケーションです)。POJO の ID を ( を使用してsetId(Long id)
) 指定して永続化すると、EclipseLinkはそれを保存しません(つまり、レコードは保存されますが、id は eclipseLink によって自動生成されます)。
@GeneratedValue を持つ列の値を手動で指定する方法はありますか?
この問題に関するいくつかの考えを次に示します。
@GeneratedValue をまったく使用せずに問題を回避しようとしましたが、列を手動で AUTO_INCREMENTed に定義するだけです。ただし、EclipseLink は主キーを検証するため (そのため、null、ゼロ、または負の数ではない可能性があります) 、 ID を手動で提供する必要があります。例外メッセージには、eclipselink.id_validation を指定する必要があることが示されていますが、これは何の違いもないようです (注釈を付け@PrimaryKey(validation = IdValidation.NONE)
ましたが、同じメッセージが表示されます)。
明確にするために:私はEclipseLink(2.4.0)を永続化プロバイダーとして使用していますが、それから切り替えることはできません(プロジェクトの大部分はEclipseLink固有のクエリヒント、注釈、およびクラスに依存しています).
編集(回答に応じて):
カスタム シーケンス:独自のシーケンスを実装しようとしました。DefaultSequence のサブクラス化を試みましたが、EclipseLink が教えてくれますInternal Exception: org.eclipse.persistence.platform.database.MySQLPlatform could not be found
。しかし、私はチェックしました:クラスはクラスパスにあります。
そこで、別のクラス NativeSequence をサブクラス化しました。
public class MyNativeSequence extends NativeSequence {
public MyNativeSequence() {
super();
}
public MyNativeSequence(final String name) {
super(name);
}
@Override
public boolean shouldAlwaysOverrideExistingValue() {
return false;
}
@Override
public boolean shouldAlwaysOverrideExistingValue(final String seqName) {
return false;
}
}
しかし、私が得るものは次のとおりです。
javax.persistence.RollbackException: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [de.dfv.datenbank.domain.Mitarbeiter[ id=null ]], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
...
Caused by: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [de.dfv.datenbank.domain.Mitarbeiter[ id=null ]], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
at org.eclipse.persistence.exceptions.ValidationException.nullPrimaryKeyInUnitOfWorkClone(ValidationException.java:1451)
...
(わかりやすくするために、スタック トレースは短縮されています)。これは私が以前に受け取ったのと同じメッセージです。NativeSequence をサブクラス化すべきではありませんか? もしそうなら、Sequence や StandardSequence の抽象メソッドに何を実装すればよいかわかりません。
また、(メソッドをオーバーライドせずに) サブクラス化するだけで、クラスが期待どおりに機能することにも注意してください。ただし、 false を返すとshouldAlwaysOverrideExistingValue(...)
、単一の値はまったく生成されません (プログラムをステップ実行したところ、getGeneratedValue()
一度も呼び出されませんでした)。
また、トランザクション内に特定の種類のエンティティを 8 つ挿入すると、データベースに 11 レコードが作成されました (一体何!?)。
編集 (2012-09-01):問題の解決策がまだありません。独自のシーケンスを実装しても解決しませんでした。私が必要としているのは、ID を明示的に設定しない (自動生成される) 方法と、ID を明示的に設定できる方法 (データベースでのレコードの作成に使用される方法) です。
列を自分でauto_incrementとして定義し、@GeneratedValueを省略しようとしましたが、検証が開始され、そのようなエンティティを保存できません。値 != 0 および != ゼロを指定すると、mysql は主キーが重複していると警告します。
試すアイデアやオプションが不足しています。どれでも?(賞金を開始)