Komponenten-basierte Entwicklung Teil 13: Persistenz mit Hibernate I

Werbung
Komponenten-basierte Entwicklung
Teil 13: Persistenz mit Hibernate I
Komponenten – WS 2014/15 – Teil 13/Hibernate
18.12.14 1
Literatur
[13-1]
Müller, Bernd; Wehr, Harald: Java Persistence API 2. Hanser, 2012.
[13-2] Beeger, Robert et al.: Hibernate. Persistenz in Java-Systemen mit
Hibernate 3. dpunkt, 2006
[13-3] http://sourceforge.net/projects/hibernatesample/
[13-4] http://hibernate.org/
[13-5] http://mvnrepository.com/artifact/org.hibernate
Wenn Sie beim Implementieren Probleme haben, benutzen Sie Google.
Auf der Site www.stackoverflow.com sind fast alle Programmierprobleme
mit Lösungen erläutert.
Komponenten – WS 2014/15 – Teil 13/Hibernate
2
Was macht Hibernate
• Hibernate realisiert die JPA-Schnittstelle in der Version 2.0.
Siehe: http://de.wikipedia.org/wiki/Hibernate_(Framework)
• JPA = Java Persistence API
Siehe: http://de.wikipedia.org/wiki/Java_Persistence_API
• Hibernate orientiert sich der Struktur und Benennung der
Klassen, nicht an der der unterliegenden Tabellen in der
Datenbank.
• Die Fehlermeldungen sind meist nichts sagend, irreführend oder
werden erst gar nicht ausgegeben.
In diesem Teil wird die XML-basierte Variante beschrieben; es
gibt noch die mit Annotationen.
Komponenten – WS 2014/15 – Teil 13/Hibernate
3
Maven und Hibernate
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.7.Final</version>
</dependency>
In diesem Foliensatz wird nur der Core benutzt.
Komponenten – WS 2014/15 – Teil 13/Hibernate
4
Das Indische Restaurant – Die Objekte
Customer
Set
1:N
Place
Explanation
1:1
List
N:M
Menu
List
•
•
Es wird ein indisches Restaurant modelliert.
Gäste (Customers) sitzen an Tischen (Places) und bestellen (Order)
•
Gerichte aus der Karte (Menu). Da die Gerichte scharf oder auch
vegetarisch sein können, gibt es zu jedem Gericht eine Erläuterung
(Explanation).
•
Es werden alle Arten von Beziehungen benutzt, die durch PointerStrukturen realisiert werden.
Die N:M-Beziehung wird durch gegenseitige Referenzierung erreicht.
•
Komponenten – WS 2014/15 – Teil 13/Hibernate
5
Die JavaBeans I
public class Customer {
private int id;
private String firstName;
private String lastName;
private boolean vegetarian;
… getter/setter …
}
Customer
Explanation
List
Set
Place
Menu
Realisierung der
1:N-Relation
public class Place {
private int id;
private int number;
private int seats;
private Date date;
private Set customers= new HashSet();
private List orders= new ArrayList();
… getter/setter …
}
Komponenten – WS 2014/15 – Teil 13/Hibernate
Erste Hälfte der
N:M-Relation
6
Die JavaBeans II
Customer
public class Menu {
private int ide;
private String name;
List
Set
private double price;
private List tables= new ArrayList();
Place
private Explanation e_id;
… getter/setter …
}
Zweite Hälfte der
Explanation
Menu
N:M-Relation
public class Explanation {
private int id;
private String text;
private Menu menu;
… getter/setter …
}
Komponenten – WS 2014/15 – Teil 13/Hibernate
Realisierung der
1:1-Relation
Es müssen also alle
Zeiger deklariert
sein.
7
Das Indische Restaurant – Die Tabellen
Customer
Explanation
N:1/0
1:1
N:M
Places
Menu
Ordered
Für eine N:M-Beziehung ist
eine weitere Tabelle erforderlich.
Komponenten – WS 2014/15 – Teil 13/Hibernate
•
•
•
Statt Place (für Tisch) müsste es eigentlich
Table heißen,
Statt Ordered (für Bestellung) eigentlich
order heißen.
Da aber Table und Order in SQL
Schlüsselworte sind und Hibernate mit den
Back-Ticks diese Bedeutung nicht aufhebt,
mussten hier die Tabellen umbenannt
werden.
8
Die Tabellen I
CREATE TABLE `indianrestaurant`.`customer` (
`id` INT NOT NULL AUTO_INCREMENT,
`FirstName` VARCHAR(45) NULL,
`LastName` VARCHAR(45) NULL,
`Vegetarian` BIT NOT NULL,
`id_table` INT,
PRIMARY KEY (`id`));
Realisierung der
1:N-Relation
Customer
Explanation
Places
Menu
Ordered
CREATE TABLE `indianrestaurant`.`place` (
`id` INT NOT NULL AUTO_INCREMENT,
`Num` INT NOT NULL,
Tabelle ist frei
`Seats` INT NULL DEFAULT 1,
von Verwaltung
`clock` TIMESTAMP,
PRIMARY KEY (`id`));
Komponenten – WS 2014/15 – Teil 13/Hibernate
9
Die Tabellen II
CREATE TABLE `indianrestaurant`.`explanation`(
`id_e` INT NOT NULL AUTO_INCREMENT,
`menu` INT,
`Text` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id_e`));
Realisierung der
1:1-Relation
Customer
Explanation
Places
Menu
Ordered
CREATE TABLE `indianrestaurant`.`menu` (
`id_e` INT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(45) NOT NULL,
`Price` FLOAT NOT NULL,
PRIMARY KEY (`id_e`),
CONSTRAINT `menu_explanation`
FOREIGN KEY (`id_e`) REFERENCES `explanation` (`id_e`));
Komponenten – WS 2014/15 – Teil 13/Hibernate
10
Die Tabellen III
Customer
Explanation
Places
Menu
CREATE TABLE `indianrestaurant`.`ordered` (
`id_place` INT,
`id_menu` INT,
`ind` INT
Gegenseitige
);
Verbindung der
N:M-Relation
Ordered
Attribut für
Reihenfolge
(List)
Hibernat erstellt nicht automatisch die Tabellen;
diese müssen von Hand samt Datenbank erstellt werden.
Komponenten – WS 2014/15 – Teil 13/Hibernate
11
Hibernate Konfiguration I - hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
… … …
</session-factory>
</hibernate-configuration>
Komponenten – WS 2014/15 – Teil 13/Hibernate
Hier kommt
die Konfiguration
hinein
Immer gleich
bleibender
Kopf
12
Hibernate Konfiguration I - hibernate.cfg.xml
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
JDBC-Treiber
</property>
<property name="hibernate.connection.url">
Datenbank-Name
jdbc:mysql://localhost/indianrestaurant
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection password"></property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.jdbc.batch_size">0</property>
<property name="transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory
</property>
Datenbank-Typ
<property name="show_sql">true</property>
Gibt die SQLStatements
aus – Debugging!
Komponenten – WS 2014/15 – Teil 13/Hibernate
13
Hibernate Konfiguration II - hibernate.cfg.xml
<mapping
<mapping
<mapping
<mapping
•
resource="Place.hbm.xml"/>
resource="Customer.hbm.xml"/>
resource="Menu.hbm.xml"/>
resource="Explanation.hbm.xml"/>
Verweise auf
Tabellendefinitionen
Es ist üblich für jede Klasse eine eigene Tabellendefinitionsdatei
anzulegen.
Weitere
Möglichkeiten
<property name="format_sql">true</property>
<property name="use_sql_comments">true</property>
•
•
format_sql formatiert die ausgegebenen SQL-Statements etwas
use_sql_comments sorgt dafür, dass der Sinn der SQL-Statements
kommentiert wird.
Komponenten – WS 2014/15 – Teil 13/Hibernate
14
Hibernate Konfiguration III - log4j
log4j.rootCategory=INFO, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-5p - %m%n
• Es wird log4j zur Ausgabe im Konsolenfenster benutzt.
• Dies ist hier ein erster Vorschlag.
• Diese Werte kommen in die Datei log4j.properties
Komponenten – WS 2014/15 – Teil 13/Hibernate
15
Anordnung der Dateien bei netbeans
Komponenten – WS 2014/15 – Teil 13/Hibernate
16
Hibernate Konfiguration IV – Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
Kopf
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="de.htw_berlin.f4.kbe.hibernate.Customer"
table="customer">
Tabelle
… … …
</class>
Abbildungen
</hibernate-mapping>
Klasse
Nach dieser Struktur sind alle Mapping-Dateien aufgebaut. Im folgenden
wird der Rahmen nicht mehr dargestellt.
Komponenten – WS 2014/15 – Teil 13/Hibernate
17
Hibernate Konfiguration V – Customer.hbm.xml
<id name="id" column="id" type="integer">
<generator class="native"/>
</id>
<property name="firstName" type="string"
Definition des
Schlüssels
column="FirstName"
not-null="true"/>
<property name="lastName"
type="string" column="LastName"
not-null="true"/>
<property name="vegetarian" type="boolean" column="Vegetarian"/>
Struktur: Name – Hibernate-Type - Spalte
class="native" bedeutet, dass die Datenbank-internen Verfahren
zur Generierung der Schlüssel benutzt werden, hier: auto_increment
Komponenten – WS 2014/15 – Teil 13/Hibernate
18
Hibernate Konfiguration VI – Place.hbm.xml
<id column="id" name="id" type="integer">
Wie bei
<generator class="native"/>
Customer
</id>
<property name="number" type="integer"
column="num" not-null="true"/>
<property name="seats" type="integer"
column="seats"/>
<property name="date"
type="timestamp" column="clock" not-null="true"/>
<list name="orders" table="ordered" lazy="true">
N:M-Relation
<key column="id_place"/>
<list-index column="ind"/>
<many-to-many class="de.htw_berlin.f4.kbe.hibernate.Menu"
column="id_menu"/>
</list>
<set name="customers" lazy="true">
1:N-Relation
<key column="id_table"/>
<one-to-many class="de.htw_berlin.f4.kbe.hibernate.Customer"/>
</set>
Komponenten – WS 2014/15 – Teil 13/Hibernate
19
Bemerkungen I
<list name="orders" table="ordered" lazy="true">
<key column="id_place"/>
<list-index column="ind"/>
<many-to-many class="de.htw_berlin.f4.kbe.hibernate.Menu"
column="id_menu"/>
</list>
• key column="id_place" gibt in der Tabelle ordered den Verweis auf sich
selbst an.
• list-index column="ind" definiert das Attribut für die Reihenfolge in der
Liste
• many-to-many class=ABC column=DEF gibt die N:M-Beziehung mit
Verweis auf die andere Klasse (ABC) sowie das Attribut von der Klasse
ABC an.
• lazy="true" bedeutet, dass nur dann aus der Datenbank gelesen wird,
wenn es nötig ist, also zum spätesten Zeitpunkt.
Komponenten – WS 2014/15 – Teil 13/Hibernate
20
Bemerkungen II
<set name="customers" lazy="true">
<key column="id_table"/>
<one-to-many class="de.htw_berlin.f4.kbe.hibernate.Customer"/>
</set>
• key column="id_table" definiert den Namen des Attributs in der
Tabelle für den Customer.
• <one-to-many class="...Customer"> legt den Verweis auf die andere
Tabelle mit dem Attribut key column fest.
• lazy="true" bedeutet, dass nur dann aus der Datenbank gelesen wird,
wenn es nötig ist, also zum spätesten Zeitpunkt.
Komponenten – WS 2014/15 – Teil 13/Hibernate
21
Hibernate Konfiguration VII – Menu.hbm.xml
<id name="id" type="integer">
<column name="id_e" />
<generator class="foreign">
Index als
<param name="property">e_id</param>
Fremdschlüssel
</generator>
</id>
<property name="name" type="string" column="Name" not-null="true"/>
<property name="price" type="double" column="Price" not-null="true"/>
<list name="tables" table="ordered" lazy="true" inverse="true">
<key column="id_menu"/>
<list-index column="ind"/>
<many-to-many class="de.htw_berlin.f4.kbe.hibernate.Place"
column="id_place"/>
</list>
<one-to-one name="e_id"
class="de.htw_berlin.f4.kbe.hibernate.Explanation" constrained="true" />
1:1-Relation
Komponenten – WS 2014/15 – Teil 13/Hibernate
22
Bemerkungen I
<list name="tables" table="ordered" lazy="true" inverse="true">
<key column="id_menu"/>
<list-index column="ind"/>
<many-to-many class="de.htw_berlin.f4.kbe.hibernate.Place"
column="id_place"/>
</list>
Die N:M-Beziehung nun gespiegelt.
Unten noch einmal die Konfiguration von Place
<list name="orders" table="ordered" lazy="true">
<key column="id_place"/>
<list-index column="ind"/>
<many-to-many class="de.htw_berlin.f4.kbe.hibernate.Menu"
column="id_menu"/>
</list>
Komponenten – WS 2014/15 – Teil 13/Hibernate
23
Bemerkungen II
• Wird auf der Ebene der Tabellen eine Beziehung zwischen zwei
Klassen realisiert, so wird in eine der beiden Tabellen ein
zusätzliches Attribut eingefügt, das nicht zum Modell gehört.
• Dieses Attribut erscheint auch nicht im UML-Diagramm.
• Dieses Attribut wird auch Join-Spalte genannt.
• Die Tabelle mit der Join-Spalte heißt Eigentümer der Beziehung,
die andere Tabelle heißt dann invers.
• Daher muss eine der betroffenen Tabellen inverse="true" haben.
• Hier betrifft es eine birektionale Beziehung; daher ist es egal,
welche die Eigentümer- und welche in inverse Tabelle ist.
Komponenten – WS 2014/15 – Teil 13/Hibernate
24
Hibernate Konfiguration VIII – Explanation.hbm.xml
<id name="id" type="integer">
<column name="e_id"/>
<generator class="native"/>
</id>
<one-to-one name="menu" class="de.htw_berlin.f4.kbe.hibernate.Menu"
cascade="save-update"/>
<property
name="text" type="string" column="Text" not-null="true"/>
• cascade="save-update" bedeutet, dass Änderungen an die Tabelle für
die Klasse Menu weiter gegeben werden.
Komponenten – WS 2014/15 – Teil 13/Hibernate
25
Das Hauptprogramm I
public class App {
private SessionFactory sessionFactory;
private ServiceRegistry serviceRegistry;
private void prologue() {
try {
Configuration config= new Configuration().configure();
serviceRegistry= new StandardServiceRegistryBuilder()
.applySettings(config.getProperties()).build();
sessionFactory= config.buildSessionFactory(serviceRegistry);
SessionFrame.setFactory(sessionFactory);
} catch( HibernateException ex ) {
ex.printStackTrace();
throw new RuntimeException(ex.getMessage());
}
}
private void epilogue() {
StandardServiceRegistryBuilder.destroy(serviceRegistry);
}
Komponenten – WS 2014/15 – Teil 13/Hibernate
26
Bemerkungen
• prologue() baut den Hibernate-Kontext auf. Es wird eine SessionFactory generiert, die während des ganzen Programmlaufs
benutzt wird.
• epilogue() beendet den Hibernate-Kontext. Ohne diese Routine verbleibt
•
für jeden Programmlauf ein wartender Thread.
SessionFrame.setFactory(sessionFactory) setzt die Factory in eine
andere Klasse, die später erklärt wird.
Komponenten – WS 2014/15 – Teil 13/Hibernate
27
Das Hauptprogramm II - main
public static void main( String[] args ) {
App me= new App();
me.prologue();
try {
me.runner();
} catch (RuntimeException ex) {
ex.getStackTrace();
} finally {
me.epilogue();
}
}
•
•
Hiermit wird sichergestellt, dass in jedem Falle epilogue() aufgerufen
wird.
Per Konvention werden immer RuntimeException geworfen.
•
•
Der Stacktrace ist für das Suchen nach Fehlermeldungen wichtig.
Runner() ist das „eigentliche“ Programm.
Komponenten – WS 2014/15 – Teil 13/Hibernate
28
Das Hauptprogramm III - runner
Customers custer= new Customers();
custer.deleteAll();
custer.load();
custer.show();
Menues offer= new Menues();
offer.load();
offer.show();
Places tabs= new Places();
tabs.load();
tabs.show();
Die rot gekennzeichneten Klassen
sind Hilfsklassen zur Benutzung
der Beans.
Komponenten – WS 2014/15 – Teil 13/Hibernate
custer.sitAtTable(1,"Herbert");
custer.sitAtTable(1,"Hildegard");
custer.sitAtTable(2,"Daniel");
custer.sitAtTable(3,"Jana");
Orders ords= new Orders();
ords.order(1,"Malai Kofta");
ords.order(1,"Malai Kofta");
ords.order(2,"Mattar Paneer");
ords.order(3,"Dinkelkernotto");
29
Klasse Customers I
Das ist eine
innere (lokale)
Klasse.
public void load() {
class doThis implements DoHibernate {
@Override public void execute(Session session) {
session.save(new Customer("Herbert","Doener",true));
session.save(new Customer("Hildegard","Momms",false));
session.save(new Customer("Daniel","Maier",true));
session.save(new Customer("Jana","Moires",true));
}
}
SessionFrame.doIt(new doThis());
}
•
Die load()-Funktionen füllen initial die am Anfang leeren DatenbankTabellen. save() schreibt am Ende der Transaktion das Objekt in die
Datenbank.
•
Alle Funktionen von Hibernate können Exceptions werfen, so dass ein trycatch-Rahmen um den eigentlichen Code immer wieder geschrieben
werden muss (Boilerplate und DRY).
•
Hier ist der Rahmen in eine einzige Klasse ausgelagert.
Komponenten – WS 2014/15 – Teil 13/Hibernate
30
Klasse SessionFrame I
public class SessionFrame {
private static SessionFactory sessionFactory;
public static void setFactory(SessionFactory factory) {
sessionFactory= factory;
}
Das ist nun der Beginn der Klasse, die den Rahmen realisiert.
Unten steht das Interface für die Füllung des Rahmens.
public interface DoHibernate {
public void execute(Session session);
}
Komponenten – WS 2014/15 – Teil 13/Hibernate
31
Klasse SessionFrame II
public static void doIt(DoHibernate obj) {
1.Teil des
Session session= null; Transaction tx = null;
Rahmens
try {
session= sessionFactory.openSession();
tx= session.beginTransaction();
Das ist der
obj.execute(session);
eigentliche
tx.commit();
Teil
} catch( HibernateException ex ) {
ex.getStackTrace();
if(tx!= null) {
try { tx.rollback();
} catch(HibernateException exRollBack) {}
}
throw new RuntimeException(ex.getMessage()) ;
} finally {
try {
if(session!=null) { session.close();}
2.Teil des
} catch(Exception exClose) {}
Rahmens
}}}
Komponenten – WS 2014/15 – Teil 13/Hibernate
32
Klasse Customers II
public void deleteAll() {
HQL
class doThis implements DoHibernate {
@Override public void execute(Session session) {
String hqlDelete= "delete Customer";
int deletedEntities= session.createQuery(hqlDelete)
.executeUpdate();
}
}
SessionFrame.doIt(new doThis());
}
•
•
Das ist nun der Code zum Löschen aller Objekte (einer Tabelle).
Es wird die HQL, die Hibernate Query Language, benutzt.
•
•
Sie ist dem SQL sehr ähnlich, operiert aber auf Objekten.
Das Ganze läuft wie der gerade vorgestellte Teil im Rahmen von
SessionFrame.
•
Die Operation zum Ausführen von HQL heißt executeUpdate().
Komponenten – WS 2014/15 – Teil 13/Hibernate
33
Klasse Customers III
public void show() {
Konvertierung
HQL
class doThis implements DoHibernate {
zu einer Liste
@Override public void execute(Session session) {
System.out.println("Kunden:");
for (Object elem : session.createQuery("from Customer").list()) {
Customer custer= (Customer) elem;
System.out.println("Name: "+custer.getFirstName()+" "+
custer.getLastName()+" veggie: "+custer.getvegetarian());
}
}
}
SessionFrame.doIt(new doThis());
}
•
•
•
Hier werden alle Objekte (einer Tabelle) vom Typ Customer selektiert.
Dann werden die selektierten Objekte in eine List gebracht und in der
Foreach-Schleife ausgewertet.
Customer hat keine Referenzen auf andere Objekte, wenn die referenzierten
Objekte auch gelesen werden sollen, ist dazu ein Join in HQL erforderlich.
Komponenten – WS 2014/15 – Teil 13/Hibernate
34
Klasse Places
public void load() {
class doThis implements DoHibernate {
@Override public void execute(Session session) {
session.save(new Place(1,2, new Date()));
session.save(new Place(2,4, new Date()));
session.save(new Place(3,4, new Date()));
session.save(new Place(4,1, new Date()));
}
}
SessionFrame.doIt(new doThis());
}
•
Die load()-Funktionen füllen initial die am Anfang leeren Datenbank-Tabellen.
save() schreibt am Ende der Transaktion das Objekt in die Datenbank.
•
Die show()-Funktion ist analog zu der der Klasse Customer aufgebaut.
Komponenten – WS 2014/15 – Teil 13/Hibernate
35
Klasse Menues
public void load() {
class doThis implements DoHibernate {
private Menu build(String name, double price, String explain) {
Explanation expl= new Explanation(explain);
Menu meal= new Menu(name,price,expl);
expl.setMenu(meal);
Etwas lustlose
return meal;
Erläuterungen
}
@Override public void execute(Session session) {
session.save(build("Dinkelkernotto", 12.5, "A"));
session.save(build("Sambhara", 7.5, "B"));
session.save(build("Korianderchutney", 3.7, "C"));
session.save(build("Mattar Paneer", 5.0, "D"));
session.save(build("Methi Chicken Curry", 6.5, "E"));
session.save(build("Biriyani", 5.0, "F"));
session.save(build("Malai Kofta", 3.6, "G"));
}
} SessionFrame.doIt(new doThis());}
•
Hier werden die Objekte Menu und Explanation (1:1-Relation) in ihre Tabellen
gebracht (Achtung! SQL-Constraint-Bedingung).
Komponenten – WS 2014/15 – Teil 13/Hibernate
36
Noch einmal der runner()
Customers custer= new Customers();
custer.deleteAll();
custer.load();
Erledigt
custer.show();
Menues offer= new Menues();
offer.load();
offer.show();
Places tabs= new Places();
tabs.load();
tabs.show();
Das kommt nun...
custer.sitAtTable(1,"Herbert");
custer.sitAtTable(1,"Hildegard");
custer.sitAtTable(2,"Daniel");
custer.sitAtTable(3,"Jana");
Orders ords= new Orders();
ords.order(1,"Malai Kofta");
ords.order(1,"Malai Kofta");
ords.order(2,"Mattar Paneer");
ords.order(3,"Dinkelkernotto");
Komponenten – WS 2014/15 – Teil 13/Hibernate
37
Jemand setzt sich an einen Tisch I
public void sitAtTable(int tableNumb, String name) {
final int tableNumber= tableNumb;
final String CustomerName= name;
class doThis implements DoHibernate {
private void build(...) {...}
@Override public void execute(Session session) {
build(session,tableNumber,CustomerName);
}
}
SessionFrame.doIt(new doThis());
}
•
Hier wird wieder mit einer inneren Klasse gearbeitet, aber es müssen
Parameter übergeben werden.
•
Globale Daten (Parameter z.B.) müssen zum Zugriff in inneren Klassen als
final, also als Konstanten, benutzt werden. Daher werden die Parameter
umkopiert.
•
Die build()-Rountine wird auf der nächsten Folie erläutert.
Komponenten – WS 2014/15 – Teil 13/Hibernate
38
Jemand setzt sich an einen Tisch II
String HQL1= "select place from Place as place where place.number=:numm";
String HQL2= "select customer from Customer as customer"+
" where customer.firstName=:name";
private void build(Session session, int tableNumber, String name) {
Iterator itrTable = session.createQuery(HQL1)
.setInteger("numm",tableNumber).iterate();
Iterator itrCustom= session.createQuery(HQL2)
.setString("name",name).iterate();
if(itrTable.hasNext() && itrCustom.hasNext()) {
Place table= (Place) itrTable.next();
Customer person= (Customer) itrCustom.next();
table.getCustomers().add(person);
} else {
throw new RuntimeException("Unknown table or customer");
}}
•
HQL1 und HQL2 sind zwei Selects mit einer where-Klausel.
•
:numm bzw. :name sind symbolische Namen wie bei den prepared
Statements. Mit setInteger() und setString() werden sie gesetzt.
Komponenten – WS 2014/15 – Teil 13/Hibernate
39
Bemerkungen
session.createQuery(HQL1).setInteger("numm",tableNumber).iterate()
In einem Stück wird der Parameter gesetzt, das Query ausgeführt und
dessen Ergebnis zu einem Iterator umgewandelt (oben war es eine List).
itrTable.hasNext() && itrCustom.hasNext()
Hier wird entsprechend dem Iterator-Interface abgefragt, ob beide
Objekte existieren.
table.getCustomers().add(person);
Und nun wird in das Set der Klasse Place über dessen Attribut
Customers per add() eine Person eingefügt.
Komponenten – WS 2014/15 – Teil 13/Hibernate
40
Nun wird etwas bestellt I
public void order(int tableNum, String meal) {
final int tableNumber= tableNum;
final String mealName= meal;
class doThis implements DoHibernate {
private void build(...) { … }
@Override public void execute(Session session) {
build(session,tableNumber,mealName);
}
}
SessionFrame.doIt(new doThis());
}
•
Hier wird wieder mit einer inneren Klasse gearbeitet, aber es müssen
Parameter in final-Variablen kopiert übergeben werden.
•
Die build()-Rountine wird auf der nächsten Folie erläutert.
Komponenten – WS 2014/15 – Teil 13/Hibernate
41
Nun wird etwas bestellt I
String HQL1= "select place from Place as place where place.number=:numm";
String HQL2= "select menu from Menu as menu where menu.name=:meal";
private void build(Session session, int placeNumber, String mealName) {
Iterator itrTable= session.createQuery(HQL1)
.setInteger("numm", placeNumber).iterate();
Iterator itrMeal = session.createQuery(HQL2).
.setString("meal",mealName).iterate();
if(itrTable.hasNext() && itrMeal.hasNext()) {
Place table= (Place) itrTable.next();
Menu meal= (Menu) itrMeal.next();
table.getOrders().add(meal);
meal.getTables().add(table);
} else {
throw new RuntimeException("Unknown place or meal");
}}
•
Das läuft nach demselben Schema ab: Es werden zwei Objekte per HQLSelect ausgewählt und...
•
gegenseitig in die jeweils andere Liste eingetragen.
Komponenten – WS 2014/15 – Teil 13/Hibernate
42
Output (Auszug) I
Dez 18, 2014 1:30:21 PM org.hibernate.annotations.c..... <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
Dez 18, 2014 1:30:21 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.7.Final}
OK, keine
Dez 18, 2014 1:30:21 PM org.hibernate.cfg.Environment <clinit>
Properties
INFO: HHH000206: hibernate.properties not found
Dez 18, 2014 1:30:21 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: /hibernate.cfg.xml
OK, die
Dez 18, 2014 1:30:21 PM org.hibernate.cfg.Configuration …
Konfig-Datei
INFO: HHH000040: Configuration resource: /hibernate.cfg.xml
Dez 18, 2014 1:30:21 PM org.hibernate.cfg.Configuration addResource
INFO: HHH000221: Reading mappings from resource: Place.hbm.xml
Dez 18, 2014 1:30:21 PM org.hibernate.cfg.Configuration addResource
INFO: HHH000221: Reading mappings from resource: Customer.hbm.xml
Dez 18, 2014 1:30:21 PM org.hibernate.cfg.Configuration addResource
INFO: HHH000221: Reading mappings from resource: Menu.hbm.xml
Dez 18, 2014 1:30:21 PM org.hibernate.cfg.Configuration addResource
INFO: HHH000221: Reading mappings from resource: Explanation.hbm.xml
Dez 18, 2014 1:30:21 PM org.hibernate.cfg.Configuration doConfigure Das bedeutet:
INFO: HHH000041: Configured SessionFactory: null
OK!
Das hier ist der Beginn, wo Hibernate seine Initialisierung dokumentiert.
Komponenten – WS 2014/15 – Teil 13/Hibernate
43
Output (Auszug) II
Hibernate: delete from customer
Hibernate: insert into customer (FirstName,
Hibernate: insert into customer (FirstName,
Hibernate: insert into customer (FirstName,
Hibernate: insert into customer (FirstName,
Kunden:
Name: Herbert Doener veggie: true
Die
Name: Hildegard Momms veggie: false
mit
Name: Daniel Maier veggie: true
Name: Jana Moires veggie: true
Das Löschen
mit deleteAll()
LastName,
LastName,
LastName,
LastName,
Ausgaben
show()
Vegetarian)
Vegetarian)
Vegetarian)
Vegetarian)
values
values
values
values
(?,
(?,
(?,
(?,
?,
?,
?,
?,
?)
?)
?)
?)
Die Inserts
mit load()
Das ist der Teil, wo mit load() die Gäste in die Tabelle Customer
dokumentiert werden.
Komponenten – WS 2014/15 – Teil 13/Hibernate
44
Die Datenbank nach einem Lauf
Komponenten – WS 2014/15 – Teil 13/Hibernate
45
Nach dieser Anstrengung etwas Entspannung...
Komponenten – WS 2014/15 – Teil 13/Hibernate
46
Herunterladen