生成されたlong
"ID"を主キーとして使用する単純なJPAエンティティがあります。
_@Entity
public class Player {
private long id;
protected Player() {
// Do nothing; id defaults to 0L
}
@GeneratedValue
@Id
public long getId() {
return id;
}
protected void setId(final long id) {
this.id = id;
}
// Other code
}
_
このタイプのオブジェクトのライフサイクルのある時点で、JPAはsetId()
を呼び出して、生成されたID値を記録する必要があります。私の質問は、whenこれが起こるのか、そしてどこにこれを記載したドキュメントがあるかです。 JPA仕様を調べましたが、明確な声明が見つかりません。
JPA仕様には次のように記載されています(強調を追加)。
管理対象エンティティインスタンスは、永続コンテキストに現在関連付けられている永続的なidentityを持つインスタンスです。
_@Id
_を有効にするには、オブジェクトをmanagedにする必要があると言っているのですか? EntityManager.persist()
のドキュメントでは、(インスタンスを追加managedおよび永続化)(強調を追加)しているため、_@Id
_はそのメソッドによって設定されていますか?または、EntityTransaction.commit()
を呼び出すまでそうではありませんか?
_@Id
_が設定されている場合、JPAプロバイダーごとに、おそらくは生成戦略ごとに異なる場合があります。しかし、それが設定されているライフサイクルの最も早い時点について作成できる最も安全な(移植可能な、仕様に準拠した)仮定は何ですか?
.persist()を呼び出しても、id値は自動的に設定されません。 JPAプロバイダーは、エンティティが最終的にdbに書き込まれる前に設定されていることを確認します。したがって、トランザクションがコミットされるときにIDが割り当てられると想定するのは正しいことです。しかし、これが唯一の可能なケースではありません。 .flush()を呼び出すと、まったく同じことが起こります。
トーマス
更新:Geekのコメントに注意してください。 -> GenerationType.Identityが使用される場合、エンティティがdbに書き込まれる前に、プロバイダーによってIDが設定されません。この場合、データベースレベルでの挿入プロセス中にIDの生成が発生します。とにかく、JPAプロバイダーは、エンティティが後で更新され、生成されたIDが@Idアノテーション付きプロパティで利用できるようにします。
知る限りでは、IDは永続コンテキストがフラッシュされるときにのみ割り当てられることが保証されています。より早く割り当てることもできますが、生成戦略によって異なります。
JSR 338:JavaTM Persistence 2.1 /3.5.3エンティティのライフサイクルコールバックメソッドのセマンティクス、
エンティティが永続化または削除された後、
PostPersist
およびPostRemove
コールバックメソッドがエンティティに対して呼び出されます。これらのコールバックは、これらの操作がカスケードされるすべてのエンティティで呼び出されます。PostPersist
メソッドとPostRemove
メソッドは、それぞれデータベースの挿入操作と削除操作の後に呼び出されます。これらのデータベース操作は、永続化、マージ、または削除操作が呼び出された直後に発生するか、フラッシュ操作が発生した直後に発生する可能性があります(トランザクションの終了時など)。 生成された主キー値は、PostPersist
メソッドで利用できます。
可能性のある(個人的に推定可能な)例外は GeneratorType.TABLE
コンテナが使用する値をフェッチし、PrePersist
の前にそれを設定する可能性があります。私は常にid
でPrePersist
を使用します。この動作が指定されているかどうか、または他のベンダーで動作しない可能性があります。
重要な編集
すべてのアプリケーションサーバーがPrePersist
の前にidを設定するわけではありません。 JPA_SPEC を追跡できます。