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.

Benutzer-Avatar
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:

  1. AttributeOverride um Spaltenzuordnungen zu überschreiben und
  2. AssociationOverride zum Überschreiben von Join-Spalten / -Tabellen.

Keiner von beiden hilft bei GeneratedValue.

Benutzer-Avatar
Juan Francisco Montanaro

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;

1014280cookie-checkMappedSuperclass – SequenceGenerator in Unterklasse ändern

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy