MappedSuperclass – SequenceGenerator in Unterklasse ändern
Lesezeit: 3 Minuten
Ich verwende JPA2 mit Hibernate und versuche, eine gemeinsame Basisklasse für meine Entitäten einzuführen. Bisher sieht es so aus:
@MappedSuperclass
public abstract class BaseEntity {
@Id
private Long id;
@Override
public int hashCode() {
// ...
}
@Override
public boolean equals(Object obj) {
// ...
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
}
Allerdings gibt es für jede Tabelle eine Sequenz $entityname_seq die ich als meinen Sequenzgenerator verwenden möchte. Wie kann ich das von meiner Unterklasse aus einstellen? Ich denke, ich muss @GeneratedValue überschreiben und einen neuen SequenceGenerator mit @SequenceGenerator erstellen.
rbento
Ja, es ist möglich. Sie können den Standard-Generatornamen mit überschreiben @SequenceGenerator Anmerkung.
Basisklasse
@MappedSuperclass
public abstract class PersistentEntity implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "default_gen")
protected Long id = 0L;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
}
Sequenz (SQL)
create sequence role_seq;
Abgeleitete Klasse
@Entity
@Table(name = "role")
@SequenceGenerator(name = "default_gen", sequenceName = "role_seq", allocationSize = 1)
public class Role extends PersistentEntity implements Serializable
{
private static final long serialVersionUID = 1L;
@NotNull
@Size(max = 32)
private String name;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
Dieser Ansatz funktionierte gut in Hibernate 4.1.x, aber nicht in EclipseLink 2.x.
bearbeiten
Laut Kommentar scheint es mit EclipseLink 2.6.1-RC1 zu funktionieren.
Ich habe mit EclipseLink 2.6.1-RC1 getestet und es hat auch funktioniert.
– leocborges
11. August 2015 um 14:39 Uhr
Das sind gute Nachrichten. Danke! Ich werde die Antwort bearbeiten.
– rbento
11. August 2015 um 14:57 Uhr
Außerdem muss für alle Unterklassen der @SequenceGenerator definiert sein, da sonst Fehler für das Mapping geworfen werden
– Stephen Senkomago Musoke
29. August 2015 um 12:28 Uhr
Dies ist eine falsche Lösung. Es funktioniert nur, solange Sie nur eine Unterklasse von haben PersistentEntity. Angenommen, Sie erstellen die Entität “Gruppe”, die sich ebenfalls erweitert PersistentEntity. Sie erhalten dann eine Fehlermeldung, weil Sequence Generator default_gen innerhalb derselben Persistenzeinheit zweimal definiert ist. (EclipseLink 2.6.2)
– Peterh
25. März 2016 um 12:15 Uhr
In der Tat, wie von JEE-7 angegeben: “Der Geltungsbereich des Generatornamens ist global für die Persistenzeinheit (über alle Generatortypen hinweg).” Auch wenn es bei einigen Implementierungen irgendwann funktioniert, ist es kein Standardverhalten.
– benjamin.donze
11. Mai 2016 um 7:47 Uhr
In JPA ist das mit Annotationen nicht möglich. Die Anmerkung selbst kann nicht überschrieben werden. Die Entität erbt alle Zuordnungsinformationen von Zugeordnete Superklasse. Es gibt nur zwei Anmerkungen, die verwendet werden können, um Zuordnungen neu zu definieren, die von zugeordneten Superklassen geerbt wurden:
Mit EclipseLink können Sie a Customizer. DescriptorCustomizer interface definiert eine Möglichkeit, alle Informationen über einen jpa-Deskriptor (auch als persistente Entität bezeichnet) anzupassen.
public class SequenceCustomizer implements DescriptorCustomizer {
@Override
public void customize(ClassDescriptor descriptor) throws Exception {
descriptor.setSequenceNumberName(descriptor.getTableName());
}
}
und in Ihrer zugeordneten Oberklasse:
@MappedSuperclass
@Customizer(SequenceCustomizer.class)
public abstract class AbstractEntity implements Serializable {
...
}
Ich schreibe dies, da es als Kommentar zur akzeptierten Antwort zu unlesbar wird:
Ich habe ein BaseEntity die jede andere Entität erbt von:
BaseEntity.java:
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ID")
private Long id;
Ich habe dann zwei Entitäten User und Order von denen beide erben BaseEntity während auch die @SequenceGenerator Anmerkung:
Benutzer.java:
@SequenceGenerator(name = "SEQ_ID", sequenceName = "SEQ_USER", allocationSize = 1)
public class User extends BaseEntity { ... }
Bestellung.java:
@SequenceGenerator(name = "SEQ_ID", sequenceName = "SEQ_ORDER", allocationSize = 1)
public class Order extends BaseEntity { ... }
Es funktioniert auf H2 mindestens mit 2 Sequenzen SEQ_USER und SEQ_ORDERS:
select SEQ_USER.nextval from dual;
select SEQ_ORDERS.nextval from dual;
10142800cookie-checkMappedSuperclass – SequenceGenerator in Unterklasse ändernyes