Mit JAXB erzeugte Klassen persistieren (Hibernate)

Status
Nicht offen für weitere Antworten.

pocketom

Bekanntes Mitglied
Wir generieren unsere Klassen aus XML Schema Dateien. Jede Klasse wird im XML Schema einmal abstrakt definiert, mit allen Membervariablen. Davon wird eine (meist "leere") Ableitung erzeugt der dann (ausschliesslich) Methoden & Logic hinzugefügt werden. Mittels
[XML]
<xsd:annotation>
<xsd:appinfo>
<jaxb:class name="Document" ref="com.ourpackage.OurClass"/>
</xsd:appinfo>
</xsd:annotation>
[/XML]
wird der JAXB Java Generator dazu bewegt bereits vorhandene konkrete Klassen nicht mehr zu überschreiben da dort ja Funktionalität angehängt wird. Die abstrakten Klassen jedoch werden jedes Mal neu generiert und die alten werden überschrieben. Das ganze ist mit Maven verknüpft und funktioniert so ganz wunderbar, solange bis Hibernate ins Spiel kommt.

Denn jetzt brauchen wir ja Hibernate Annotations über den Definitionen der Membervariablen. Die Member befinden sich jedoch nur in den abstrakten Klassen welche ja immer wieder überschrieben werden.

Hat irgendwer eine gute Idee wie man das geschickt regeln kann? Kann man die Hibernate Annotationen bereits in die XML Schemas einbringen so dass sie automatisch über den Membervariablen in den generierten Klassen auftauchen?
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
So ganz einfach ist das nicht. Generell ist das eigentliche Problem, dass das Maven Plugin die JAXB Klassen bei jedem Compile erneut erstellt.

Es gibt aber eine Lösung und zwar über Interfaces:
Java:
@XmlJavaTypeAdapter(FooAdapter.class)
public interface IFoo { // Interface mit XmlAdapter
    public int getId();
    public void setId(int id);

    public String getValue();
    public void setValue(String value);
}

@Entity
@Table("foo")
public class FooImpl implements IFoo { // Hibernate Klasse
    @Id int id;
    String value;

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getValue() { return value; }
    public void setValue(String value) { this.value = value; }
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "foo")
public class Foo { // JAXB Klasse
    @XmlAttribute(required = true)
    protected int id;
    @XmlAttribute(required = true)
    protected String value;

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getValue() { return value; }
    public void setValue(String value) { this.value = value; }
}

public class FooAdapter extends XmlAdapter<Foo, IFoo> {
    @Override
    public Foo marshal(IFoo v) throws Exception {
        Foo foo = new Foo();
        foo.setId(v.getId());
        foo.setValue(v.getValue());
        return foo;
    }

    @Override
    public IFoo unmarshal(Foo v) throws Exception {
        IFoo foo = new FooImpl();
        foo.setId(v.getId());
        foo.setValue(v.getValue());
        return foo;
    }
}

Sehr umständlich aber Wirkungsvoll :D
 

pocketom

Bekanntes Mitglied
Ok, klingt wirklich sehr umständlich. Wenn ich nun die abstrakte Basisklasse um sagen wir eine Variable erweitere, dann müsste ich die Änderung auch in den anderen nachtragen oder? Bzw. in der Hibernateklasse wird ja jede Variable nopchmal deklariert oder?
 

Noctarius

Top Contributor
Genau das. War nach langem Suchen die einzige funktionierende Lösung da die Annotations sich nicht sauber vererben.
 

pocketom

Bekanntes Mitglied
Ok, das heisst selbst wenn ich die Annotations dauerhaft in die abstrakten Klassen bekommen würde (z.B. PostProcessing Script in der Maven Phase process-sources anwenden), so könnte ich die Ableitungen davon nicht gescheit persistieren, verstehe ich das so richtig? Woran scheitert es da?
 

Noctarius

Top Contributor
Annotations benötigen selbst das Annotation @Inherited um vererbt zu werden. Dies gilt dann aber leider nur für Annotations in Klassen und nicht in Interfaces.

Abstract Classes brauchst du hier auch nicht. Wenn die Annotations sauber vererbt werden würden (bei mir kam noch das Problem mit dem Interface-driven hinzu) könntest du von den JAXB Klassen ableiten und die Hibernate Annotations in der abgeleiteten Klasse hinterlegen. Aber auch hier wäre das Problem, dass du alle Getter überschreiben müsstest um die Annotations sauber unterzubringen. Generell ist JAXB mit JPA / Hibernate / Eclipselink recht unhandlich.

Wenn du aber das obige einmal gebaut hast (und deine Klassen nicht alle 2 Tage Änderungen erfahren - hier wäre dann eh irgendwie ein Designfehler oder schlechte Planung im Spiel) ist es ganz sauber nutzbar. Halt immer das Interface benutzen und der Adapter kümmert sich bei JAXB ums Konvertieren vor der Serialisierung.
 

Noctarius

Top Contributor
Du könntest noch versuchen das Mapping für Hibernate komplett in xml zu Verfassen, dass habe ich zugegebener Maßen nie probiert, da ich kein Freund davon bin. Das Problem daran ist dann aber, dass die Klassen vermutlich nicht mehr in JAXB funktionieren, da Hibernate eine perfide Liebe zu Proxies hat.
 

velaluka

Aktives Mitglied
Hallo,
wie siehts hier mit aus....Noch nie selber verwendet, aber zum Glück wieder eingefallen;)
Ciao velalulka
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
Ich vermute, dass HyperJaxb das oben genannte einfach nur automatisch erzeugt und nutzt. Was die Sache aber natürlich angenehmer macht.

Problem bei mir war damals, ich brauchte EclipseLink :D

Edit:
Ok nope, HyperJaxb packt JPA und JAXB Annotations zusammen in eine Klasse (und baut direkt XML-Workarounds für JAXB ein). Gibt es auch direkt als Maven Plugin.
 
Zuletzt bearbeitet:

pocketom

Bekanntes Mitglied
HyperJAXB klingt echt ein bischen wie die eierlegende Wollmilchsau zu diesem Thema :-D

Ich werds ausprobieren...!
 

pocketom

Bekanntes Mitglied
So, maven-hyperjaxb3-plugin installiert und zum laufen gebracht. Sieht auf den ersten Blick ganz gut aus. Zu jeder generierten Java Klasse werden jetzt auch Hibernate Annotations hinzugefügt. Vorläufig einziges Problem:

Er generiert die Annotations sowohl für die abstrakten als auch die konkreten Klassen:

Java:
@Entity(name = "oneit.AbstractExchangeableBusinessObject")
@Table(name = "ABSTRACTEXCHANGEABLEBUSINESS_0")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class AbstractExchangeableBusinessObject implements Equals, HashCode
{
...
...
...
}
Java:
@Entity(name = "oneit.ExchangeableBusinessObject")
@Table(name = "EXCHANGEABLEBUSINESSOBJECT")
public class ExchangeableBusinessObject extends AbstractExchangeableBusinessObject implements Equals, HashCode
{
...
...
...
}

Was muss ich denn nun persistieren? 2 Tables könnens ja in dem Fall auch kaum sein da man die abstrakten Klassen ja eh nicht instanziieren kann... ???
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
I XML mit JAXB und Annotations aufbauen klappt nicht wie gewollt Allgemeines EE 5
pkm Root resource - Klassen werden nicht gefunden. Allgemeines EE 2
K Spring Namensgebung bei Klassen Allgemeines EE 7
L Sessions - Unterschiedlich in verschiedenen Klassen? Allgemeines EE 4
R JAVA EE - eigene Klassen aus EJB übernehmen Allgemeines EE 2
J Einige Klassen werden nicht resolved Allgemeines EE 7
P Können abstrakte Klassen über WSDL versendet werden? Allgemeines EE 3
I Klassen werden nicht für Import erkannt eclipse EE Allgemeines EE 2
S In Eclipse werden die "Servlet-Klassen" nicht gefu Allgemeines EE 2
N Lokation von Bean Klassen? Allgemeines EE 5
N Reflektion und die Liste abgeleiteter Klassen/Interfaces Allgemeines EE 6
M TagLib und Referenzen zwischen Klassen Allgemeines EE 4
M Servlets | work - Klassen nicht im WAR File Allgemeines EE 5
P JSP Servlets/ Java Klassen für FTP FileUpload (Bilder) + DB Allgemeines EE 3
D Controller-Klassen eines Servlets testen mit JUnit Allgemeines EE 3
F Klassen und zugriffs Problem "Help wanted"! Allgemeines EE 16
M HTML-Klassen Allgemeines EE 2
S JSP auch mit Klassen? Allgemeines EE 2
K JSP anfänger. auf eigene klassen zu greifen Allgemeines EE 8
S zugriff von jsp-seiten auf java klassen Allgemeines EE 3

Ähnliche Java Themen

Neue Themen


Oben