JPA複合キー+シーケンス
-
04-07-2019 - |
質問
単純なJPAまたはJPA + Hibernate拡張機能では、複合キーの要素がシーケンスである複合キーを宣言できますか?
これは私の複合クラスです:
@Embeddable
public class IntegrationEJBPk implements Serializable {
//...
@ManyToOne(cascade = {}, fetch = FetchType.EAGER)
@JoinColumn(name = "APPLICATION")
public ApplicationEJB getApplication() {
return application;
}
@Column(name = "ENTITY", unique = false, nullable = false, insertable = true, updatable = true)
public String getEntity() {
return entity;
}
@GeneratedValue(strategy = GenerationType.AUTO, generator = "INTEGRATION_ID_GEN")
@SequenceGenerator(name = "INTEGRATION_ID_GEN", sequenceName = "OMP_INTEGRATION_CANONICAL_SEQ")
@Column(name = "CANONICAL_ID", unique = false, nullable = false, insertable = true, updatable = true)
public String getCanonicalId() {
return canonicalId;
}
@Column(name = "NATIVE_ID", unique = false, nullable = false, insertable = true, updatable = true)
public String getNativeId() {
return nativeId;
}
@Column(name = "NATIVE_KEY", unique = false, nullable = false, insertable = true, updatable = true)
public String getNativeKey() {
return nativeKey;
}
//...
}
すでに application
、 entity
、 nativeId
、および nativeKey
の値を提供しています。以下のようなエンティティを構築したい:
IntegrationEJB i1 = new IntegrationEJB();
i1.setIntegrationId(new IntegrationEJBPk());
i1.getIntegrationId().setApplication(app1);
i1.getIntegrationId().setEntity("Entity");
i1.getIntegrationId().setNativeId("Nid");
i1.getIntegrationId().setNativeKey("NK");
そして em.persist(i1
)を呼び出すと、 canonicalId
が生成され、統合が挿入されます。
これは可能ですか?もしそうなら、簡単な方法は何ですか? (アプリケーションが提供するキーやネイティブSQLを使用しないことを好みます)。
解決
プレーンなJPAではこれは不可能だと思います。
他のヒント
JPA 2仕様では、複合PKに@GeneratedValueを使用することは指定されていません。
JPA仕様から:
11.1.17 GeneratedValueアノテーション
GeneratedValueアノテーションは、 主キーの値の生成戦略。の GeneratedValue注釈は、主キープロパティに適用されるか、 Idと組み合わせたエンティティまたはマッピングされたスーパークラスのフィールド 注釈。[97] GeneratedValueアノテーションの使用は 単純な主キーをサポートする必要があります。の使用 GeneratedValue注釈は、派生主キーではサポートされていません。
異なるシナリオでは、@ GeneratedValueを使用する単純なPK(@Id)を持つ親エンティティがあり、その後、親から生成されたIDを含む複合PKを持つ子エンティティを持つことができます。別の列。
- FK列で生成されたIDを継承するように、子に親エンティティへの@ManyToOne関係を与えます。
- 次に、エンティティに対して指定された@IdClassと、エンティティ内の2つの@Id列を介して、複合PKを子に与えます。
@Entity public class ParentEntity {
@Id
@GenerateValue(IDENTITY) // If using DB auto-increment or similar
int id;
// ...
}
@Entity @IdClass(ChildId.class) public class ChildEntity { // The child table will have a composite PK: // (parent_ID, child_name) @Id @ManyToOne int parentEntity;
@Id
String childName;
String favoriteColor; // plus other columns
// ...
}
// child Id attributes have the same name as the child entity // however the types change to match the underlying PK attributes // (change ParentEntity to int) public class ChildId implements Serializable {
int parentEntity;
String childName;
public ChildId() { //... }
// Add extra constructor & remove setter methods so Id objects are immutable
public ChildId(int parentEntity, String childName) { //... }
public int getParentEntity() { //... }
// make Id objects immutable:
// public void setParentEntity(int parentEntity) { //... }
public String getChildName() { //... }
// public void setChildName(String childName) { //... }
}
次のようにしてください:
@TableGenerator(name = "canonicalKeys", allocationSize = 1, initialValue = 1)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "canonicalKeys")
@Column(name = "CANONICAL_ID", unique = false, nullable = false, insertable = true, updatable = true)
public String getCanonicalId() {
return canonicalId;
}
この方法では、シーケンスを使用する代わりに、テーブルを使用できます。
このような複合主キーを構築しているように見えます例。私は自分のデータベースで同様の問題を突っ込んでいたが、次のように直接SQLを呼び出すことができるのではないかと思った:
nextval( 'hibernate_sequence')を選択します
それは不正行為だと思う;-)