Java JPA ORM Mapping

roker002

Commander
Registriert
Dez. 2007
Beiträge
2.061
Hallo zusammen. Ich habe ein kleines Projekt zur Übungszwecken erstellt und möchte ein ORM Interface implementieren.

Soweit so gut, ich habes das nötige aufgestellt:

1. Maven Konfiguration
2. JPA: DB, Consistence.xml, Interface, Klasse, UnitTest, Hibernate Connection

Code:
@Entity
public class TW implements ITW
{
	@Id
	@GeneratedValue
	private Long Id;
	private String Name;
	private Integer WUC;
	private String Location;
	@Temporal(TemporalType.DATE)
	private Date JD;
	@Temporal(TemporalType.DATE)
	private Date LT;
	
	@ManyToOne(targetEntity = TF.class)
	private ITF TF;
	
	@ManyToMany(targetEntity = TP.class)
	private List<ITP> TaskProcessings = new ArrayList<ITP>();

Persistance.xml sieht folgend aus.

Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
	version="2.0">
	<persistence-unit name="dst_pu">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		<mapping-file>META-INF/TW.xml</mapping-file>
		<mapping-file>META-INF/orm.xml</mapping-file>
		<properties>
			<property name="hibernate.connection.driver_class" value="org.h2.Driver" />
        	<property name="hibernate.connection.url" value="jdbc:h2:/tmp/database/dst;AUTO_SERVER=TRUE;MVCC=true" />
        	<property name="hibernate.connection.username" value="sa" />
        	<property name="hibernate.connection.password" value="" />
        	<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
        	<property name="hibernate.hbm2ddl.auto" value="create-drop" />
        	<property name="hibernate.show_sql" value="false" />
			<property name="javax.persistence.validation.mode" value="NONE" />
			<property name="hibernate.ejb.interceptor" value="interceptorNameSpace.SQLInterceptor" />
		</properties>
	</persistence-unit>
</persistence>

Mein Problem ist: Beim ausführen von Testunits habe ich
Unable to find XML mapping file in classpath: META-INF/TW.xml

Ich bin kein erfahrener Hibernat'iker aber ich dachte ich komme irgendwie alleine dahinter. Muss ich TW.xml selbst erstellen und mappen? Ich dachte, dass das System für mich das ganze tut. Habe ich vielleicht irgendwo anders einen Fehler gemacht? Kompilieren geht es ohne Probleme. Es liegt also kein Syntaxfehler vor!
Persistence.xml ist unter META-INF/ aufzufinden!

Ein Hinweis würde mir auch vollkommen reichen!
 
Zuletzt bearbeitet:
Ohne Spring habe ich das auch noch nicht aufgesetzt (da habe ich keine persistence.xml nötig). Wenn ich aber deine XML mit dem Beispiel vergleiche, fehlen mir irgendwie bei dir die class-Knoten. Das Mapping erzeugt er ja aus deinen Annotations und um die zu finden braucht er vermutlich diesen Hinweis. Außerdem wird in dem Beispiel gesagt, dass die persistence.xml direkt im META-INF liegen solle, d.h das könntest du auch noch probieren.
 
Du musst beachten, dass das die persistence.xml im META-INF Verzeichnis nicht fälschlicherweise im src/main/webapp sondern im src/main/resources Verzeichnis liegen muss.
Weiterhin könnte ich mir vorstellen, dass deine <mapping-file> ebenfalls dort liegen müssen. Ggf. muss der Pfad angepasst werden.
 
ja, ich verstehe nicht was es mit den Mapping Files auf sich hat! Muss ich die manuell erstellen oder werden diese automatisch generiert?
 
Kommt auf die IDE an.
In Intellij kannst du über die pu ein XML Mapping File erstellen.
Allerdings gehts natürlich manuell auch.
 
Wie geht das? Die Metamodels werden schon generiert. Aber ich habe wirklich keine Ahnung wie es unter Eclipse die Erzeugung der XML gehen sollte. Habs im internet nicht finden können
 
Hast du im Eclipse das Hibernate Plugin installiert? Da sollts doch sicher was geben.
 
Eine Verstehe ich nicht, wieso eigentlich noch eine XML ORM Dateie geben sollte! Mit Metadaten und Annitation sollte es ausreichen zu arbeiten. Konktrete Definition ist auch über Annotation möglich.
Hm ich werde mir das irgendwann mal noch einmal ansehen, aber vorerst reicht es mir!

Bei interesse, hier gibts einen manuellen ansatz!
http://www.integratingstuff.com/201...-create-jpa-mappings-for-a-java-domain-model/
 
Zuletzt bearbeitet:
Ich merk grad erst das du ja von der TU Wien bist und Distributed Systems Technologies machst :D

Du brauchst deshalb die XML weil dus ohne den Annotations machen solltest ;-)
 
Zuletzt bearbeitet:
Ja stimmt schon... hatte eigentlich auch vorher Interesse an Hibernate, aber ich stell mir gerade selbst die Frage, ob Hibernate eine vernünftige Lösung ist. Ich meine, Entweder/Oder ist doch kein Weg innerhalb eines Frameworks. Es gibt ja keine Konsequenzen diesbezüglich, wie man programmiert. Man verschmutzt ja die eigene Software mit solchen Frameworks. Irgendwann wird Entweder/Oder abgeschafft und dann gucken die Leute dumm, weil deren Produkt vom gesammten Framework nicht unterstützt wird.

Ich konnte zumindest nicht herauslesen, dass ich ohne Annotation in der Aufgabelösung das Problem lösen soll. das O/R Mapping funktioniert mit Annotation auch nicht, wenn man die UnitTests laufen lässt. Was ist also der Sinn des ganzen? Enweder macht man nur mit XML mappings oder nur Annotation. Linq2SQL funktioniert ja ganz gut mit Attributen. Sogar mit der Datenbank wo keine direkte Linq Unterstützung gibt. Klar hat Linq auch schwächen, aber man kann ja immer noch direkte Abfragen schreiben. Hm ja mittlerweile gibt es so etwas fast nicht mehr aber SQLite hatte auch bis vor kurzem kein Linq im Treiber, jetzt schon.

Ich verlege einfach die Vorlesung auf den nächstmöglichen Termin. Trotzdem danke für die Hilfe.

Je mehr ich mit Java arbeite, um so mehr mag ich Java nicht, ehrlich gesagt. Es gibt ein Problem und 1000 Lösungen dazu. Klar ich übertreibe es, aber irgendwann mal muss man sich auch entscheiden...
Allein Maven hat bei Eclipse Marketplace min 10 verschiedene Downloadoptionen. Da fragt man sich, welche die richtige ist.


http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software


PS: Es ist nett, dass hier auch Leute aus TU Wien sind ;)
 
Naja es gibt halt Vor- und Nachteile bei der Nutzung von Annotations oder XML....Solange man aber die JPA Annotations verwendet kann man Hibernate leicht gegen ein anderes Framework austauschen welches auf JPA beruht. Das ist ja grad der Sinn der Sache.
Also kann man auch nicht von Verschmutzung der Software reden.

In der Aufgabenstellung stand, dass man bis auf TW alles mit Annotations machen sollte und TW ohne => mit XML...
Nur damit man halt mal den Unterschied sieht und mal mit beiden gearbeitet hat.

Anhand der Tests kannst du ja eh ablesen wie du was annotieren bzw im XML angeben musst!?

PS: Ich bin aber erst ziemlich spät draufgekommen, dass das BSP von der Uni ist^^
 
Als jemand der die LVA schon gemacht hat und sich auch so gut auskennt, muss ich dir leider sagen, dass du dich einfach noch nicht auskennst. Bemüh dich schau es dir genau an. Du kannst in der LVA sehr viel lernen solange du auch ein wenig Zeit investierst. Die Technologie ist mehr oder weniger State auf die Art, auch wenn ich jetzt Hibernate so allein eher nicht verwende in letzter Zeit.
 
roker002 schrieb:
Je mehr ich mit Java arbeite, um so mehr mag ich Java nicht, ehrlich gesagt. Es gibt ein Problem und 1000 Lösungen dazu. Klar ich übertreibe es, aber irgendwann mal muss man sich auch entscheiden...
Allein Maven hat bei Eclipse Marketplace min 10 verschiedene Downloadoptionen. Da fragt man sich, welche die richtige ist.
Das ist so ähnlich wie wenn Windows-User sich darüber aufregen, dass in der Linux Welt alles so verwirrend ist, weil es so viele Alternativen gibt. In der heilen Microsoft-Welt schreibt eben Microsoft vor, was "richtig" ist. Kann man gut finden, muss man nicht. Vielfalt erlaubt ein Ausweichen, wenn einem etwas nicht passt.
Und de facto gibt es Standards, die einfach durch die Häufigkeit ihrer Verwendung im professionellen Bereich entstehen. In Java gibt es viele Spezifikationen, die dann von verschiedenen Projekten implementiert werden. So eine Implementierung von JPA ist z.B. Hibernate. Zusätzlich bringen diese Implementierungen noch ihren eigenen Klimbim mit, den man benutzen kann, aber aus hier bereits genannten Gründen nicht unbedingt benutzen sollte, da man damit Flexibilität aufgibt.

Zu annotations vs. XML ist meine Meinung, dass man XML hinter sich lassen sollte, wo es geht. Die Tendenz geht überall klar zu annotations. Man kann inzwischen selbst die web.xml weitestgehend ersetzen. Ich finde annotations beim mapping von entities schon deshalb passender, weil ich wenn ich die Definition einer solchen sehen will, eben das zugehörige POJO öffnen kann, in dem ich diese Information erwarten würde und nicht zusammengepfercht mit hundert anderen in einer unübersichtlichen XML-Datei.
XML ist okay zum Ablegen von Daten (selbst da bevorzuge ich schlankeres JSON), aber nicht für Konfigurationen.

P.S.: maven und Eclipse haben sich bei mir noch nie sonderlich gut vertragen. Rate zur Konsole. Damit hast du dann auch die "richtige" Lösung. ;)
 
Ich verwende ebenso die Konsole für Maven. Die ganzen Plugins dies da gibt sind alle nicht das Gelbe vom Ei.

Tumbleweed schrieb:
Zu annotations vs. XML ist meine Meinung, dass man XML hinter sich lassen sollte, wo es geht. Die Tendenz geht überall klar zu annotations. Man kann inzwischen selbst die web.xml weitestgehend ersetzen. Ich finde annotations beim mapping von entities schon deshalb passender, weil ich wenn ich die Definition einer solchen sehen will, eben das zugehörige POJO öffnen kann, in dem ich diese Information erwarten würde und nicht zusammengepfercht mit hundert anderen in einer unübersichtlichen XML-Datei.
XML ist okay zum Ablegen von Daten (selbst da bevorzuge ich schlankeres JSON), aber nicht für Konfigurationen.

Das kommt halt darauf an. Gerade bei großen Projekten wo es eine klare Rollenteilung gibt ist eventuell das Auslagern von der JPA Config schon eine gute Sache. Natürlich sieht es ein bisschen Messi aus das ganze, aber Änderungen lassen sich so einfach klar Teilen in Datenbank und POJO.
Ich selbst bin auch mehr für Annotations. Vor allem weil man da einfach eine Änderung nicht an 2 verschiedenen Orten machen muss. Alles schön beisammen und auf einen Blick ersichtlich. Sind aber manche Properties ziemlich kompliziert gemapped wird die Liste der Annotations schon ziemlich lange und aufgebläht.
Aber ich glaub da soll es halt jeder so handhaben wie er mag.
 
Tumbleweed schrieb:
Das ist so ähnlich wie wenn Windows-User sich darüber aufregen, dass in der Linux Welt alles so verwirrend ist, weil es so viele Alternativen gibt. In der heilen Microsoft-Welt schreibt eben Microsoft vor, was "richtig" ist. Kann man gut finden, muss man nicht. Vielfalt erlaubt ein Ausweichen, wenn einem etwas nicht passt.

Ich sage ja nicht, dass es bei MS anders ist. Aber ich sehe einen Vorteil bei MS. Es gibt auch mehr als 10 Lösungen für ein Problem, aber dafür gibt es nur wenige die auch Kostenlos sind. Nachteil ist natürlich, dass die Kostenlose Lösung auch viel später herauskommt, wenn es zur Standarden gehört.

@Funart
ja wenn man richtig Zeit investiert kann man sicher alles alleine hinbekommen. Leider arbeite ich und studiere nebenbei. Wenn ich nur genug Zeit hätte, würde ich mir die auch nehmen.

Ich bemängele einfach die Lösung innerhalb einer Bibliothek. Wenn man den XML mapping herausnimmt und stattdessen nur Annotation verwendet, dann würde es für alle Nutzer einfacher sein Hibernate anzuwenden. Denn es ist genau das gleiche, wenn ich innerhalb einer Software in einem Teil auf ORM setze und in dem anderen Teil mit Result Sets arbeite. Was soll dann der neuer Mitarbeiter anwenden? ORM oder die klassischen Abfragen über einen String?


Klar, LINQ, Hibernate und alle ähnliche Lösungen können nicht 100% SQL nachbilden (und umgekehrt, nicht jede Lösung innerhalb der ORM ist auch in SQL möglich). Solange die Komplexität so gering wie möglich ist, ist es viel einfacher und verständlicher mit ORM zu arbeiten als mit SQL Queries.
 
Bedenke, dass die XML Mapping Lösung die ältere ist...
Annotations sind relativ "neu" und wie so oft kann und will man meist nicht die Abwärtskompatibilität aufgeben.
 
Es läuft übrigens alles in Richtung Annotationen bei JPA. Du kannst mittlerweile mit den Annotationen so gut wie jeden Fall abdenken den du über eine extra mapping Datei abbilden kannst. Die Regel ist hier also, wenn du die Sachen mit Annotationen abbilden kannst, dann mache es!
 
roker002 schrieb:
Ich bemängele einfach die Lösung innerhalb einer Bibliothek. Wenn man den XML mapping herausnimmt und stattdessen nur Annotation verwendet, dann würde es für alle Nutzer einfacher sein Hibernate anzuwenden. Denn es ist genau das gleiche, wenn ich innerhalb einer Software in einem Teil auf ORM setze und in dem anderen Teil mit Result Sets arbeite. Was soll dann der neuer Mitarbeiter anwenden? ORM oder die klassischen Abfragen über einen String?

Eine so umfangreiche und komplexe Welt wie die von Java kann man halt nicht innerhalb von ein paar Stunden Entwicklung an der Uni überblicken oder gar verstehen (das sollte ja auch nicht das Ziel eines Studiums sein). Für Java-Neulinge ist es ziemlich normal, anfangs von der Auswahl an Möglichkeiten erschlagen, verwirrt und wie gelähmt zu sein. Aber auch wenn es für dich als Anfänger etwas unnötig kompliziert sein zu scheint, gibt es doch dafür sicherlich eine Existenzberechtigung, immerhin haben sich ja hunderte schlaue Leute darüber Gedanken gemacht, oder?
Nach ein paar tausend Zeilen Code lernt man diese Vielfalt aber durchaus zu schätzen, auch mal andere Wege einschlagen zu können ist erfrischend. Einfach dran bleiben, IMHO lohnt es sich.

Das Szenario eines Mischansatz beim DB-Zugriff macht übrigens durchaus Sinn, viele Anwendungen verwenden neben einem ORM-Mapper auch manuelle Abfragen via Result/Rowset, z.B. um auf mehrere unterschiedliche DBMS zugreifen zu können. Auch bieten die jeweilgen Mapper oft eigene SQL-Dialekte an, mit denen man dank ORM-Mapper ziemlich bequem komplexe Queries schreiben kann. Tw. ist man sogar darauf angewiesen, weil manche SQL-Statements einfach zu komplex sind oder etwa die generierte Abfrage vom Mapper zu inperformant ist.
Für die Einarbeitung eines neuen Mitarbeiters ist natürlich das Unternehmen zuständig. Und keine Sorge, jedes halbwegs vernünftige Entwicklungsteam macht sowas schon aus purem Eigennutz, weil sie nicht in unnötigen Code-Reviews ihren Verstand verlieren wollen ;). Sowas ist innerhalb von ein paar Minuten geklärt.

Bei der XML- vs Annotation-Debatte sollte man nicht vergessen, das Java jetzt schon einige Jahre alt, enorm gewachsen ist und sehr viel Wert auf Abwärtskompatibiltät legt. Es gibt zahllose Systeme die sich seit Jahren in kontinuierlicher Entwicklung befinden. Da ist es doch schön auch auf moderne Herangehensweisen und Bibliotheken zurückgreifen zu können, ohne das bestehende System komplett neuschreiben zu müssen. Zwar weiß heute jeder herangehende Java-Dev, das Annotations um Welten besser sind als lästige XML, aber es gibt sicherlich immer Entwickler die eine XML schneller zusammen geschreiben haben als sich mit Annotations zu befassen (die sind dann aber bestimmt 20 Jahre älter ;) ).

ORM - SQL
XML - Annotations
Licht - Dunkel
Gut - Böse
Das Leben ist nicht Schwarz und Weiß, sondern eine einzige Graue Masse voll von Optionen. Warum sollte es also beim Entwickeln anders sein? :)
 
@nor_

also Eclipse und XML haben sich noch nie vertragen. Ich habe oft abstürze gehabt als ich Softwaremodellierung mit Eclipse gemacht habe. Wirklich nicht empfehlenswert. Hm, wenn es schon die stabile Version oft einknickt, dann will ich nicht Wissen wie es bei Alpha und Beta Versionen war. XML wird sicher noch lange bleiben, weil es halt menschen gibt, die solche Dateien auch lesen möchten.

@Abwärtskompatitbilität
ist etwas für sich. Man kann über 2-3 Versionen das Unterstützen, aber die Innovation wird dadurch extrem gebremst.
 
Das Mapping ist ja nur notwendig wenn du nicht mit Annotations arbeitest.

Ich arbeite mit Hibernate ohne Spring und das sieht dann so aus:
persistence.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">

    <persistence-unit name="H2DB">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <property name="hibernate.connection.url" value="jdbc:h2:tcp://localhost/D:/testdb"/>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
            <property name="hibernate.connection.username" value="SA"/>
            <property name="hibernate.connection.password" value=""/>
            <property name="hibernate.archive.autodetection" value="class"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
        </properties>
    </persistence-unit>
    <persistence-unit name="MckoiDB">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>Model.CarEntity</class>
        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:mckoi://localhost/"/>
            <property name="javax.persistence.jdbc.driver" value="com.mckoi.JDBCDriver"/>
            <property name="javax.persistence.jdbc.user" value="test"/>
            <property name="javax.persistence.jdbc.password" value="test"/>
            <property name="hibernate.archive.autodetection" value="class"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MckoiDialect"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
            <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
        </properties>
    </persistence-unit>
</persistence>

Das Mapping wie in der zweiten Konfiguration enthalten ist nicht nötig
Code:
<class>Model.CarEntity</class>
da ich automatisch über die Annotation die Klassen mappe:
Code:
<property name="hibernate.archive.autodetection" value="class"/>

Beispiel der Entity Class (mit Composite Key):
Code:
@NamedQueries({
        @NamedQuery(name="Car.findAll",
                query="SELECT c FROM CarEntity c"),
        @NamedQuery(name="Car.findByName",
                query="SELECT c FROM CarEntity c WHERE c.name = :name"),
})
@Entity
@Table(name = "Car")
@IdClass(CarEntityPK.class)
@Access(AccessType.FIELD)
public class CarEntity {
    @Id
    @Column(name = "id")
    private int id;
    @Id
    @Column(name = "serial")
    private int serial;
    @Basic
    @Column(name = "name")
    private String name;
    @Version
    private Long version;

    public CarEntity(){}
    public CarEntity(int id, int serial, String name){
        this.id = id;
        this.serial = serial;
        this.name = name;
    }

    public int getId() {
        return id;
    }

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


    public int getSerial() {
        return serial;
    }

    public void setSerial(int serial) {
        this.serial = serial;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        CarEntity carEntity = (CarEntity) o;

        if (id != carEntity.id) return false;
        if (serial != carEntity.serial) return false;
        if (name != null ? !name.equals(carEntity.name) : carEntity.name != null) return false;

        return true;
    }


Als Ergänzung mag evtl eine Information noch hilfreich sein:

JPA hat erstmal nichts mit Hibernate zu tun. JPA ist wie der Name schon sagt nur eine API. Damit wird eben das ORM umgesetzt (Die Entityklassen in dem Falle mit den Annotations). Zugriffe auf Datenbanken können damit aber nicht umgesetzt werden.
Hibernate ist einer der Implementierungen neben Eclipselink (Referenz Implementierung), OpenJPA etc.

Deswegen gibt es auch völlig verschiedene Beispiele im Netz. Mal wird die persistence.xml verwendet aber man sieht immer häufiger die hibernate.cfg.xml Konfiguration.
Das gleiche bei der Implementierung wo die Sessionfactory verwendet wird (Hibernate spezifisch) und seltener der Entitymanager.

Wenn ich die Möglichkeit haben möchte zwischen den verschiedenen Providern wechseln zu können (Eclipselink, Hibernate, OpenJPA....) dann sollte ich eben keine spezifischen Implementierungen verwenden.
D.h.
Persistence.xml verwenden und nicht hibernate.cfg.xml und eben den EntityManager und nicht die Sessionfactory. Bei Verwendung des Entitymanagers unter Hibernate wird natürlich im Hintergrund auch eine Sessionfactory erstellt (auf die ich sogar Zugriff hätte um spezifische Hibernate Implementierungen zu nutzen) der mir dann aber eben nur die Möglichkeiten bietet die jeder Provider unterstützt.

Trotz allem muss man aber trotzdem aufpassen da je nach Provider einige Dinge unterschiedlich interpretiert werden.
 
Zuletzt bearbeitet:
Zurück
Oben