Hibernate (OR-Mapping) rrer Roland F Furrer Urs Frei 1 Inhalt Beispielanwendung Herkömmlicher Datenbankzugriff Hibernate { { { { { { Idee Bestandteile Beispielanwendung Collection Vererbung Datenbankabfragen Hib t mit it XD l t Hibernate XDoclets Hibernate mit Annotationen 2 Beispielanwendung Benutzer * Person •Kürzel •Vorname •Nachname * Termine Termine •Datum Uhrzeit •Uhrzeit •Titel •Beschreibung 3 Herkömmlicher Datenbankzugriff JDBC { { { { { update i insert delete select create Connectionverwaltung Es geht auch einfacher! 4 Hibernate Idee Applikation DB Z Zugriff iff Datenbank Select Update p Delete Insert Applikation Hibernate Datenbank Z iff auff DB wird Zugriff i d nicht i ht mehr h selber lb programmiert!! i t!! 5 Grundelemente Applikation pp Anwendung in Java Hibernate Open-Source-Produkt unter www.hibernate.org Datenbank Open-Source-Produkt HSQLDB unter www.hsqldb.org 6 Bestandteile der Beispielanwendung DB config File (xml) { { M Mapping i Fil File ((xml) l) { Definiert die Verbindung zur DB Art der DB j g Welches Javaobjekt gehört zu welcher Tabelle J Kl (J Java Klassen (Java B Beans)) 7 Beispiel Hibernate Configfile <hibernate-configuration> <session-factory> <property name="dialect"> org.hibernate.dialect.HSQLDialect </property> <property name="connection.driver_class"> org.hsqldb.jdbcDriver </property> / t <property name="connection.username"> sa </property> <property name="connection.password"></property> <property name="connection.url"> jdbc:hsqldb:file:db/termine </property> <mapping resource="net/sf/hibernatesample/einfach/Termin.hbm.xml" /> </session factory> </session-factory> </hibernate-configuration> 8 Beispiel Hibernate Mappingfile <hibernate-mapping pp g p package= g "net.sf.hibernatesample.einfach"> p <class name="Termin"> <id name="id"> <generator class="native"/> </id> <property name="titel"/> name= titel /> <property name="beschreibung"/> p p y name="zeitPunkt"/> <property <property name="ort"/> </class> </hibernate-mapping> 9 Beispiel Java-Klasse package net.sf.hibernatesample.einfach; import java.util.Date; public class Termin { private long id; private String titel; private String beschreibung; private String ort; private Date zeitPunkt; public String getTitel () { return titel; } public void setTitel (String titel) { this.titel thi tit l = tit titel;l } public Date getZeitPunkt () { return zeitPunkt; } public void setZeitPunkt (Date zeitPunkt) { this.zeitPunkt = zeitPunkt; } .....} 10 Tabellen mit Hibernate erzeugen Erzeugen g der Tabelle in der Java-Anwendung: g Configuration configuration = new Configuration().configure(); SchemaExport export = new SchemaExport(configuration); export.create(false, p ( , true); ); Resultierendes Statement für HSQLDB: create t table t bl Termin T i ( id bigint generated by default as indentity (start with 1), titel varchar(255), beschreibung varchar(255) b h ib h (255) zeitPunkt timestamp, ort varchar(255) i kkey (id) primary ) 11 Erzeugung g g eines p persistenten Objekts private long erzeugeTermin(String titel, String beschreibung, String ort, Date zeitPunkt) { Termin termin = new Termin(); () termin.setTitel(titel); termin.setBeschreibung(beschreibung); termin setOrt(ort); termin.setOrt(ort); termin.setZeitPunkt(zeitPunkt); Session session = null; Transaction transaction = null; try { session = sessionFactory.openSession(); transaction = session.beginTransaction(); session.save(termin); transaction.commit(); } catch (HibernateException e) { ... } .... return termin.getID(); } 12 Laden, L d suchen, h aktualisieren, kt li i lö löschen h eines i persistenten Objekts Laden: Termin termin = (Termin) session.load(Termin.class, id); Suchen: Query query = session.createQuery("from Termin where ort=‘ " + ORT + “ ‘ "); Li t result List lt = query.list(); li t() Termin termin = (Termin) result.get(0); Aktualisieren: Termin termin = (Termin) session.load(Termin.class, id); Transaction transaction = session.beginTransaction(); ( Termin"); ) termin.setTitel("neuer transaction.commit(); Löschen: Termin T i ttermin i = (T (Termin) i ) session.load(Termin.class, i l d(T i l id) id); Transaction transaction = session.beginTransaction(); session.delete(termin); transaction commit(); transaction.commit(); 13 Details der Mapping-Dateien <hibernate-mapping package = "net.sf.hibernatesample.einfach"> <class name="Termin" table="termin"> <id name="id"> <generator class="native"/> class= native /> </id> <property name="titel"/> <property name="beschreibung"/> p ope y name="zeitPunkt" a e e u co u e type="timestamp" ype es a p //> column="zeit" <property <property name="ort" type="string" length="40" /> </class> </hib t i > </hibernate-mapping> 14 Objekte als Klassenmember Wir ändern die Klasse Termin so, dass der Zeitpunkt nicht mehr in einem java.util.Date gespeichert wird, sondern in einem Zeitpunkt. public class Zeitpunkt { private int minute, stunde, tag , monat, jahr; .... //mit set- und get-Methoden } public class Termin { private Zeitpunkt zeit; ...//mit set- und get-Methode } 15 Objekte als Klassenmember Die Mapping-Datei ändert sich nun wie folgt: <hibernate-mapping package = "net.sf.hibernatesample.einfach"> <class name="Termin" table="termin"> <id name="id"> <generator class="native"/> </id> <property name="titel"/> <property name="beschreibung"/> <component name="zeit"> name= zeit > <property name="minute" /> <property name="stunde" /> property name name="tag" tag //> <property <property name="monat" /> <property name="jahr" /> </component> <property name="ort" type="string" length="40" /> </class> </hibernate-mapping> 16 Umgang mit Collections Es soll nun möglich sein, einen Termin nicht an einem definierten Zeitpunkt abzuhalten sondern vorgängig alternative Zeitpunkte zu definieren: public class Termin { private List<Zeitpunkt> alternativZeiten = new ArrayList<Zeitpunkt>(); ...//mit set- und get-Methode } In der DB wird eine neue Tabelle ALT_ZEITPKT ALT ZEITPKT erzeugt erzeugt. Die Tabelle hat einen Fremdschlüssel auf die Tabelle TERMIN. Ausserdem braucht die Tabelle eine Spalte LFD_NR, die für alle Elemente in der Liste festlegt, in welcher Reihenfolge sie stehen. ALT_ZEITPKT id lfd nr lfd_nr Minute stunde tag monat jahr 1 2 22 18 1 6 2006 1 0 0 12 1 6 2006 1 1 0 18 7 6 2006 2 0 0 20 7 6 2006 17 Umgang mit Collections Die Mapping-Datei sieht dann wie folgt aus: <hibernate-mapping package = "net.sf.hibernatesample.einfach"> <class name="Termin" table="termin"> ... <list name="alternativeZeiten" table="ALT_ZEITPKT"> <k column="id"/> <key l "id"/> <list-index column="lfd_nr"/> <composite-element class="hibtest.entity.Zeitpunkt"> <property name= name="minute" minute /> <property name="stunde" /> <property name="tag" /> p p y name="monat" /> <property <property name="jahr" /> Mit Set, SortedSet, Map, </composite-element> SortedMap, etc. wird jeweils </list> entsprechend t h d verfahren. f h .... </class> </hibernate-mapping> 18 Vererbung in Hibernate public abstract class Ressource { private long id; Ressource private String name; ...// set- und get-Methoden Raum Gegenstand public class Raum extends Ressource { public class Gegenstand extends Ressource { private String gebaeude; private double wert; ...// set- und get-Methode ...// set- und get-Methode 19 Vererbung in Hibernate Tabelle je Klassenhierarchie: Die ganze Vererbung in einer einzigen Tabelle! Ressource id disc name gebaeude 1 r Physikzimmer y C1 2 g Beamer <class name=„Ressource"> <id id name="id"> "id" <generator class="native"/> </id> property name name / name="name"/> <property <discriminator column=„disc“ type=„string“ lenght=„1“/> <subclass name=„Raum“ discriminator-value=„r“> <property name=„gebaeude“/> / b l </subclass> <subclass name=„Gegenstand“ discriminator-value=„g“> <property name=„wert“/> /subclass </subclass> </class> wert 2500.00 20 Vererbung in Hibernate Tabelle je konkrete Klasse Raum Gegenstand id name gebaeude Id name wert 1 Physikzimmer C1 2 Beamer 2500 00 2500.00 <class name=„Ressource"> <id id name="id"> "id" <generator class="native"/> </id> property name name / name="name"/> <property <union-subclass name=„Raum“ table=„raum“> <property name=„gebaeude“/> </union-subclass> i b l G d“ <union-subclass name=„Gegenstand“> <property name=„wert“/> </union-subclass> /class </class> 21 Vererbung in Hibernate Tabelle je Klasse Ressource Raum id name id gebaeude 1 Physikzimmer 1 C1 <class l name=„Ressource"> R " 2 Beamer <id name="id"> <generator class="native"/> /id </id> <property name="name"/> <joined-subclass name=„Raum“ table=„raum“> <key column=„id“ /> <property t name=„gebaeude“/> b d “/ </joined-subclass> <joined-subclass name=„Gegenstand“> <key key column=„id“ column „id //> <property name=„wert“/> </joined-subclass> </class> Gegenstand id wert 2 2500.00 22 Datenbankabfragen HQL sehr ähnlich SQL Query query = session.createQuery("from Termine"); query list(); List<Termin> alleTermine = query.list(); Criteria Criteria crit = session.createCriteria(Termin.class); C C ( ) crit.add(Restrictions.eq("ort", "Hamburg")); List<Termin> termine = criteria.list(); SQL auch möglich 23 Hibernate: Ziel erreicht? Vorteile { Problem { Keine SQL Statements D fi iti Definitionsredundanz d d JJava und d XML Lösungsansätze { { XDoclet Annotationen 24 Hibernate mit XDoclet XDoclet: { { XML Mappingfile generieren Informationen für Generierung aus Javadoc 25 Hibernate mit XDoclet Bsp. p Java /** * @hibernate.class *// public class Termin { private long id; … /** * @hibernate.property */ public bli S String i getTitel() Ti l() { return titel;} public void setTitel(String titel) { this.titel = titel; } /** * hibernate.one-to-one * @hibernate.many-to-one @hib t t */ public Benutzer getInitiator() { return initiator;} ;} } 26 Hibernate mit XDoclet ((3)) VorNachteile Vorteil: { Mapping Infos näher bei Sourcen Einfacheres Ändern Konfiguration an einem Ort Nachteil: { { XML Mappingfile immer noch erforderlich z B mit Ant generiert werden Muss z.B. 27 Hibernate Annotationen Annotationen { { { { { Ermöglicht Metainformationen im Code Annotationsprozessoren bei Kompilierung In Reflection verwenden „Weiterentwicklung“ XDoclet 5 enthalten In Java 1 1.5 28 Hibernate Annotationen Bsp. @Entity public class Termin { private long id; … public String getTitel() { return titel;} public void setTitel(String titel) { this.titel = titel; } @ManyToOne(targetEntity = Benutzer.class) public Benutzer getInitiator() g () { return initiator;} } 29 Hibernate Annotationen VorNachteil Vorteil: { Kein XML Mappingfile mehr Nachteil: { J Java 1.5 1 5 wird idb benötigt. öti t Nachteil? N ht il? 30 Warum Hibernate einsetzen? Bsp Programmieraufwand für eine Tabelle Bsp. Hibernate @Entity 1 Codezeile Es funktioniert JDBC Create Table Select Insert Delete xxx Codezeilen Funktioniert es???? 31 Referenzen Hibernate www.dpunkt.de www dpunkt de ISBN 33 89864-371-9 www.hibernate.org j java.sun.com www.hsqldb.org www hsqldb org http://xdoclet.sourceforge.net/xdoclet/i p g ndex.html 32