Chiave composita JPA + sequenza
-
04-07-2019 - |
Domanda
È possibile nelle normali estensioni JPA o JPA + Hibernate dichiarare una chiave composita, dove un elemento della chiave composita è una sequenza?
Questa è la mia classe composita:
@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;
}
//...
}
Fornisco già i valori per application
, entity
, nativeId
e nativeKey
. Voglio costruire un'entità come quella qui sotto:
IntegrationEJB i1 = new IntegrationEJB();
i1.setIntegrationId(new IntegrationEJBPk());
i1.getIntegrationId().setApplication(app1);
i1.getIntegrationId().setEntity("Entity");
i1.getIntegrationId().setNativeId("Nid");
i1.getIntegrationId().setNativeKey("NK");
E quando chiamo em.persist (i1
), voglio che canonicalId
sia generato e che l'integrazione sia inserita.
È possibile? Se è così, qual è il modo semplice? (Preferisco non usare chiavi fornite dall'applicazione o sql nativo).
Soluzione
Credo che ciò non sia possibile con l'APP semplice.
Altri suggerimenti
L'uso di @GeneratedValue per PK compositi non è specificato con le specifiche JPA 2
Dalle specifiche dell'APP:
11.1.17 Annotazione GeneratedValue
L'annotazione GeneratedValue fornisce le specifiche di strategie di generazione per i valori delle chiavi primarie. Il L'annotazione GeneratedValue può essere applicata a una proprietà chiave primaria o campo di un'entità o superclasse mappata insieme all'ID annotazione. [97] L'uso dell'annotazione GeneratedValue è solo richiesto per essere supportato per semplici chiavi primarie. Uso del L'annotazione GeneratedValue non è supportata per le chiavi primarie derivate.
Tieni presente che in uno scenario diverso, puoi avere un'entità padre con un PK semplice (@Id) che utilizza @GeneratedValue e quindi avere un'entità figlio che ha un PK composito che include l'ID generato dal padre, oltre a un'altra colonna.
- Assegna al figlio una relazione @ManyToOne con l'entità padre, in modo che erediti l'ID generato in una colonna FK.
- Quindi assegna al figlio un PK composito, tramite @IdClass specificato rispetto all'entità, più due colonne @Id all'interno dell'entità.
@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) { //... }
}
Prova in questo modo:
@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;
}
In questo modo invece di usare una sequenza puoi usare una tabella.
Ho notato che sembra che tu stia costruendo una chiave primaria composita come questa esempio . Mentre cercavo un problema simile nel mio database, mi chiedevo se forse potevi chiamare sql direttamente come:
seleziona nextval ('hibernate_sequence')
Suppongo che sarebbe barare però ;-)