1 Einführung in Hibernate - EDV

Werbung
635-0.book Seite 17 Montag, 6. August 2007 12:52 12
Wir starten mit einem Beispiel, in dem wir eine Anwendung für ein
Datenbank konfigurieren, Daten erzeugen, löschen und abfragen und das
objektorientierte Konzept der Assoziation verwenden. Danach werden wir
uns die Bausteine und drei unterschiedliche Status von Hibernate ansehen,
bevor es um das Speichern, Bearbeiten, Löschen und Ändern von Objekten
geht. Am Ende des Kapitels erstellen wir dann bereits die erste Webanwendung.
1
Einführung in Hibernate
Für jede richtige Anwendung benötigt man einen Anwendungsfall. Daher starten
wir mit einem ersten Beispiel.
1.1
Erstes Hibernate-Beispiel
Unser Anwendungsfall ist süß. Wir untersuchen die Honigproduktion. Bekanntermaßen benötigen wir viele Bienen, um ein Glas Honig zu erzeugen. Um das
darzustellen, sind zwei Klassen erforderlich: Honig (engl. honey) und Biene (engl.
bee).
Bienen und Honig stehen in einer 1:n-Beziehung oder – wenn wir eine objektorientierte Terminologie verwenden möchten – es gibt eine 1:n-Assoziation zwischen der Klasse Biene und Honig. Folgende Abbildung zeigt uns das entsprechende Klassendiagramm.
Honey
-id : Integer
-name : String
-taste : String
-bees : Bee = new HashSet<Bee>()
honey 1
Bee
-id : Integer
-name : String
-honey : Honey
bees *
Abbildung 1.1 Ein Klassendiagramm
Die beiden Objekte werden wir in den unten gezeigten Tabellen in der Datenbank speichern:
17
635-0.book Seite 18 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
+ id
name
taste
honey
int4
Nullable = false
varchar(255) Nullable = true
varchar(255) Nullable = true
+ id
name
# honey_id
bee
int4
varchar(255)
int4
Nullable = false
Nullable = true
Nullable = true
Abbildung 1.2 Tabellen in Hibernate
Damit wir eine vollständige Hibernate-Anwendung erhalten, müssen wir mehrere Schritte unternehmen:
왘
Klassen erstellen
왘
Mapping zu den Datenbanktabellen festlegen, in denen Honig und Biene
gespeichert werden
왘
Hibernate-Libraries konfigurieren
왘
Hibernate konfigurieren mitsamt Datenquelle
왘
Quellcode schreiben, der unsere Klassen verwendet
Quellcode
Für dieses Beispiel finden Sie den gesamten Quellcode im Buch und auf der Webseite
zum Buch: http://www.galileocomputing.de/978. Für alle anderen Beispiele werden
im Buch nur Ausschnitte gezeigt. Das Projekt heißt FirstHibernateExample bzw. FirstAnnotationExample für die Annotation-Variante.
1.1.1 Projekt und Klassen erstellen
Java-Projekt erstellen
Erstellen Sie in Ihrer Entwicklungsumgebung ein neues Java-Projekt. Ich habe
Eclipse verwendet, aber es gibt natürlich auch sehr gute andere IDEs.
Ich habe das Projekt FirstHibernateExample genannt.
Klassen erstellen
Wir benötigen eine Klasse mit Namen Honey im Package de.laliluna.example.
Unsere Klasse hat vier Attribute:
Integer id – eine Zahl als Primärschlüssel
String name – Name des Honigs
String taste – Beschreibung des Geschmacks
java.util.Set<Bee> bees – Bienen, die den Honig erzeugt haben
18
635-0.book Seite 19 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
Ferner brauchen wir:
왘
die Getter und Setter für unsere Attribute. Diese kann man in Eclipse im Kontextmenü 폷 Source 폷 Generate Getter and Setter erzeugen.
왘
einen parameterlosen Konstruktor
왘
die Implementierung von Serializable
왘
eine toString-Methode. Diese verwenden wir für Debug-Ausgaben.
So sollte der Quellcode aussehen:
package de.laliluna.example;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
public class Honey implements Serializable {
private Integer id;
private String name;
private String taste;
private Set<Bee> bees = new HashSet<Bee>();
public Honey() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTaste() {
return taste;
}
public void setTaste(String taste) {
this.taste = taste;
}
public Set<Bee> getBees() {
return bees;
}
public void setBees(Set<Bee> bees) {
19
1.1
635-0.book Seite 20 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
this.bees = bees;
}
public String toString() {
return MessageFormat.format("Honey: {0} {1} {2}",
new Object[]{id, name, taste});
}
}
Bitte nicht vergessen
Damit eine gemappte Klasse korrekt funktioniert, denken Sie bitte immer an die folgenden Punkte:
왘
Serializable implementieren
왘
Konstruktor ohne Parameter (Defaultkonstruktor)
왘
eine ordentliche toString-Methode
Hinweis zur Java-Version
Ich habe Java Generics verwendet, die mit Java Version 5 eingeführt worden sind.
Wenn Sie Java 1.4 nutzen müssen, löschen Sie Dinge wie <Bee> und die Annotation,
die es manchmal gibt.
Annotations beginnen mit @.
Jetzt müssen wir die Klasse Bienen (Bee) mit folgenden Attributen erstellen:
왘
Integer id
왘
String name
왘
Honey honey
Das Attribut id ist wiederum der Primärschlüssel und die anderen Attribute sind
Merkmale der Klasse.
Hier gilt der gleiche »Bitte nicht vergessen«-Hinweis, den ich bei der vorherigen
Klasse gegeben habe.
Unsere Klasse:
package de.laliluna.example;
import java.io.Serializable;
import java.text.MessageFormat;
public class Bee implements Serializable {
private Integer id;
private String name;
private Honey honey;
public Bee() {
}
20
635-0.book Seite 21 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
public Bee(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Honey getHoney() {
return honey;
}
public void setHoney(Honey honey) {
this.honey = honey;
}
public String toString() {
return MessageFormat.format("{0}: id={1}, name={2}",
new Object[] { getClass().getSimpleName(), id, name });
}
}
1.1.2 Hibernate-Konfiguration
In der Konfiguration legen wir folgende Dinge fest:
왘
die Datenbank, mit der wir uns verbinden
왘
den Typ der Datenbank (MySQL, PostgreSQL, Oracle ...)
왘
die Konfigurationseinstellungen für Hibernate
왘
die Klassen bzw. XML Mappings, die eingelesen werden
Legen Sie bitte eine Datei hibernate.cfg.xml im src-Verzeichnis an. Und jetzt die
große Frage:
Annotation oder XML Mapping?
Wir haben zwei Möglichkeiten, das Mapping der Klassen auf Tabellen festzulegen:
Annotation und XML. Ich diskutiere die Unterschiede in Abschnitt 4.1, »Mapping mit
Annotation oder XML«, im Detail. Hier treffen wir einfach eine schnelle Entscheidung.
21
1.1
635-0.book Seite 22 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
Wenn Sie Java 5 oder neuer verwenden, empfehle ich, Annotations zu verwenden,
wenn nicht, haben Sie keine andere Wahl als XML.
Ich zeige Ihnen jetzt eine Annotation-Version für PostgreSQL und gebe dann die
Hinweise, was man ändern muss, um die Konfiguration für andere Datenbanken
oder XML Mappings anzupassen.
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">
jdbc:postgresql://localhost:5432/learninghibernate
</property>
<property name="connection.username">postgres</property>
<property name="connection.password">p</property>
<property name="connection.driver_class">
org.postgresql.Driver
</property>
<property name="dialect">
org.hibernate.dialect.PostgreSQLDialect
</property>
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="current_session_context_class">thread
</property>
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory
</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<mapping class="de.laliluna.example.Honey" />
<mapping class="de.laliluna.example.Bee" />
</session-factory>
</hibernate-configuration>
Die Konfiguration enthält zu Beginn die Datenbankverbindung. Anschließend
legen wir mit der Einstellung dialect fest, in welchen SQL-Dialekt Hibernate
Abfragen übersetzt.
Dann konfigurieren wir den Cache und wie sich die Session verhalten soll.
hbm2ddl.auto stellt sicher, dass Hibernate unsere Tabellen erstellt.
22
635-0.book Seite 23 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
Schließlich legen wir fest, welche Mappings gelesen werden. Wenn wir Annotations verwenden, referenzieren wir die Klassen mit <mapping class>.
Andere Datenbanken
Eine Konfiguration für MySQL benötigt folgende Anpassungen:
<property name="connection.url">
jdbc:mysql://localhost/learninghibernate
</property>
<property name="connection.username">root</property>
<property name="connection.password">r</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
Wenn Sie eine andere Datenbank verwenden möchten, müssen Sie die Einstellung connection.url und dialect anpassen. Werfen Sie einen Blick in das JavaPackage org.hibernate.dialect der hibernate.jar. Diese finden Sie im Download
von Hibernate. Dort finden Sie alle existierenden Dialekte.
Hier ein Auszug aus den unterstützten Dialekten: MySQL5Dialect, OracleDialect,
SybaseDialect, SQLServerDialect, HSQLDialect, DerbyDialect.
Die connection.url entspricht der URL einer normalen JDBC-Verbindung.
XML Mapping statt Annotation
Das XML Mapping erfolgt in XML-Dateien. Wir müssen nur eine kleine Änderung an der Konfiguration vornehmen, und zwar die beiden <mapping>-Tags
ersetzen.
<mapping resource="de/laliluna/example/Honey.hbm.xml" />
<mapping resource="de/laliluna/example/Bee.hbm.xml" />
1.1.3 Mapping
Mit dem Mapping legen wir fest, welcher Tabelle und welcher Spalte ein Attribut
einer Klasse zugeordnet ist. Wie oben bereits erwähnt, gibt es zwei Möglichkeiten: Annotation und XML.
23
1.1
635-0.book Seite 24 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
Annotation Mapping
Eine Annotation ist immer an dem @ zu erkennen. Damit können wir im Quellcode Hinweise geben. Fügen Sie einfach die folgenden Annotations hinzu.
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
@Entity
@SequenceGenerator(name = "honey_seq", sequenceName =
"honey_id_seq")
public class Honey implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,
generator="honey_seq")
private Integer id;
private String name;
private String taste;
@OneToMany(mappedBy="honey")
private Set<Bee> bees = new HashSet<Bee>();
Mit der Annotation @Entity wird bestimmt, dass unsere Klasse gemappt ist. Den
Primärschlüssel kennzeichnen wir mit @Id. Unser Primärschlüssel verwendet
eine Datenbanksequenz. Diese muss mit Hilfe von @SequenceGenerator definiert
werden, bevor wir beim Attribut id festlegen können, dass es von diesem »Generator« erzeugt wird (@GeneratedValue).
Die Annotation @OneToMany beschreibt, dass unser Attribut bees in einer 1:nBeziehung zur Klasse Bee steht. Ich möchte die genaue Festlegung der Fremdschlüsselbeziehung zwischen den Tabellen in der Klasse Bee vornehmen. Daher
habe ich den Parameter mappedBy verwendet.
Die Klasse Bee hat zwei weitere Annotations. @ManyToOne beschreibt die Beziehung aus Sicht der Klasse Bee. Mit der Annotation @JoinColumn legen wir fest,
dass in der Tabelle bee eine Fremdschlüsselspalte existiert. Da wir keinen Namen
festlegen, verwendet Hibernate die Spalte honey_id.
import
import
import
import
import
import
24
javax.persistence.Entity;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.JoinColumn;
javax.persistence.ManyToOne;
635-0.book Seite 25 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
import javax.persistence.SequenceGenerator;
@Entity
public class Bee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "bee_gen")
@SequenceGenerator(name = "bee_gen", sequenceName = "bee_id_seq")
private Integer id;
private String name;
@ManyToOne
@JoinColumn
private Honey honey;
Andere Datenbanken
Nicht alle Datenbanken unterstützen Sequenzen, um Werte für den Primärschlüssel zu erzeugen. Für die meisten Datenbanken sollte aber folgende Annotation funktionieren:
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
Sie wählt einen Generator abhängig vom konfigurierten Datenbank-Dialekt.
XML Mapping
Sie benötigen XML Mappings nur, wenn Sie keine Annotations verwenden.
In der Mapping-Datei wird die Zuordnung zwischen Attributen und Datenbankspalten festgelegt. Legen Sie die Datei Honey.hbm.xml im Package de.laliluna.example an.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping
DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping3.0.dtd" >
<hibernate-mapping package="de.laliluna.example">
<class name="Honey" table="thoney" >
<id name="id" column="id">
<generator class="sequence">
<param name="sequence">honey_id_seq</param>
</generator>
</id>
<property name="name" type="string"></property>
<property name="taste" type="string"></property>
25
1.1
635-0.book Seite 26 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
<set name="bees" inverse="true">
<key column="honey_id"></key>
<one-to-many class="Honey" />
</set>
</class>
</hibernate-mapping>
Mit <id> wird der Primärschlüssel beschrieben und wie dieser erzeugt wird. Die
»normalen« Attribute werden mit Hilfe von <property> den Tabellenspalten
zugeordnet. Wenn wir keinen Namen für die Tabellenspalte angeben
(column=«xyz«), wird der Name des Attributs übernommen.
<set> beschreibt die Beziehung zur Klasse Bee.
Da wiederum nicht alle Datenbanken Sequenzen unterstützen, können wir
Hibernate anhand des Datenbankdialekts einen Generator auswählen lassen.
Ändern Sie das Tag für den Generator wie folgt:
<generator class="native"/>
Wenn auch das nicht funktioniert, dann müssen Sie einen Blick in Abschnitt 4.4,
»Mapping von Primärschlüsseln«, werden.
Für die Klasse Bee legen Sie eine Datei Bee.hbm.xml im gleichen Java-Package an.
Als weiteres Tag wird hier <many-to-one> verwendet. Damit wird die Beziehung
aus Sicht der Klasse Bee beschrieben. Die assoziierte Klasse Honey müssen wir
nicht angeben. Sie wird von Hibernate aus dem Attribut der Java-Klasse ermittelt.
<class name="Bee" table="tbee" >
<id name="id" >
<generator class="sequence">
<param name="sequence" >bee_id_seq</param>
</generator>
</id>
<property name="name" type="string"></property>
<many-to-one name="honey"></many-to-one>
</class>
Warum type="string" und nicht type="java.lang.String"?
Wir können im Mapping auch Java-Klassen angeben. Hibernate-Typen sind aber präziser. Es gibt zum Beispiel die Typen date, timestamp und time, aber nur eine einzige
Java-Klasse java.util.Date.
Hibernate müsste raten, welchen Typen Sie meinen. Daher empfehle ich, immer die
Hibernate-Typen zu verwenden.
Generell ist die Angabe von type nur notwendig, wenn Hibernate den Typ nicht erraten kann. Bei java.util.String könnten wir uns die type-Angabe auch sparen.
26
635-0.book Seite 27 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
1.1.4 Notwendige Bibliotheken
Um Hibernate zu verwenden, benötigen wir einige Bibliotheken, alias JARDateien.
Bei Hibernate hat von 2006 nach 2007 eine Explosion von Teilprojekten stattgefunden. Erschrecken Sie sich nicht, wenn Sie Hibernate auf http://www.hibernate.org/ herunterladen. Wir benötigen nur Hibernate Core und – wenn Sie
Annotations verwenden – Hibernate Annotations.
Entpacken Sie die Datei. Im Hauptverzeichnis finden Sie die hibernate.jar. Im libVerzeichnis liegen eine Menge weiterer Bibliotheken, die wir aber nicht alle
benötigen. In der Datei README.txt ist erläutert, was wofür erforderlich ist.
Folgende Bibliotheken benötigen wir für unser Beispiel:
왘
log4j.jar
왘
hibernate3.jar
왘
ant-antlr-1.6.5.jar
왘
asm.jar
왘
commons-logging-1.0.4.jar
왘
antlr-2.7.6.jar
왘
cglib-2.1.3.jar
왘
dom4j-1.6.1.jar
왘
jdbc2_0-stdext.jar
왘
asm-attrs.jar
왘
commons-collections-2.1.1.jar
왘
ehcache-1.2.3.jar
왘
jta.jar
In Eclipse kann man diese in den Project Properties zum Java Build Path hinzufügen. Der Dialog heißt: Add External Jars.
Um Annotations nutzen zu können, muss man Hibernate Annotations herunterladen. Wir benötigen folgende Bibliotheken:
왘
ejb3-persistence.jar
왘
hibernate-annotations.jar
왘
hibernate-commons-annotations.jar
27
1.1
635-0.book Seite 28 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
Datenbanktreiber
Natürlich ist auch ein JDBC-Datenbanktreiber notwendig. Die entsprechende
Bibliothek muss noch besorgt werden. Für PostgreSQL bekommt man diesen auf
http://jdbc.postgresql.org. Der JDBC 3-Treiber ist in Ordnung, wenn Sie Java
1.4 oder neuer verwenden.
Den MySQL Connector findet man auf:
http://www.mysql.com/products/connector/j/
Einen Oracle-Datenbank-Treiber erhält man bei Oracle: http://www.oracle.com
1.1.5 Session-Factory erstellen
Eine Session-Factory ist sehr wichtig für Hibernate. Wie der Name sagt, ist diese
Klasse eine Fabrik, mit der wir Hibernate-Sessions erzeugen können, wann
immer wir diese benötigen. Eine Session spielt eine zentrale Rolle in Hibernate.
Mit Hilfe einer Session können wir Daten speichern, löschen und die Datenbank
abfragen.
Die Session-Factory initialisiert auch die Hibernate-Konfiguration. Wir müssen
wieder Annotation und XML unterscheiden. Hier zuerst die Annotation-Version.
Von der Session-Factory sollte es nur eine Instanz geben (Singleton Pattern).
Genau dies stellt die folgende Klasse sicher.
package de.laliluna.hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
public class InitSessionFactory {
/** The single instance of hibernate SessionFactory */
private static org.hibernate.SessionFactory sessionFactory;
private InitSessionFactory() {
}
static {
final AnnotationConfiguration cfg = new
AnnotationConfiguration();
cfg.configure("/hibernate.cfg.xml");
sessionFactory = cfg.buildSessionFactory();
}
public static SessionFactory getInstance() {
return sessionFactory;
}
}
28
635-0.book Seite 29 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
Wenn wir XML Mapping einsetzen, können wir folgende Zeile statt AnnotationConfiguration verwenden.
final Configuration cfg = new Configuration();
Eine AnnotationConfiguration unterstützt allerdings neben Annotation auch
XML Mappings. Sie können diese sogar bunt mischen.
1.1.6 Logging Konfiguration
Hibernate verwendet log4j für die Logausgabe. Oben haben wir ja die Bibliothek
hinzugefügt. Log4j erwartet eine Konfigurationsdatei im Hauptverzeichnis, sonst
werden wir später mit folgender Nachricht begrüßt:
log4j:WARN No appenders could be found for logger (TestClient).
log4j:WARN Please initialize the log4j system properly.
Legen Sie eine Datei mit dem Namen log4j.properties im src-Verzeichnis an. Wir
konfigurieren eine einfache Logausgabe in der Console.
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p
%c{1}:%L - %m%n
# Achtung, die vorherige Zeile wird versehendlich umgebrochen
log4j.rootLogger=debug, stdout
log4j.logger.org.hibernate=info
#log4j.logger.org.hibernate=debug
### log just the SQL
log4j.logger.org.hibernate.SQL=debug
1.1.7 Datenbank und Tabellen erstellen
Erstellen Sie eine Datenbank und achten Sie darauf, den gleichen Namen zu wählen, den wir in der connection.url der Hibernate-Konfiguration verwendet haben.
In der hibernate.cfg.xml haben wir festgelegt, dass die Tabellen von Hibernate
bei der Initialisierung erstellt werden, daher müssen wir das nicht von Hand erledigen.
<property name="hibernate.hbm2ddl.auto">create</property>
Die Einstellung create löscht die Tabellen und erstellt diese neu. Sie eignet sich
daher nur für die Entwicklung. Alternativ kann man die Einstellung update verwenden. Hibernate versucht dann, die Tabellen nur bei Bedarf zu erzeugen bzw.
29
1.1
635-0.book Seite 30 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
zu ändern. Das klappt nahezu immer. Ich würde es für den Live-Betrieb dennoch
ausschalten.
1.1.8 Testen
Wir werden eine einfache Klasse erstellen, die unser Mapping verwendet, zudem
Daten erstellt, löscht und abfragt. Ich gebe Ihnen jetzt noch ein paar Hinweise
und schlage vor, dass Sie sich dann den Quellcode der Klasse ansehen.
Wenn Sie Hibernate verwenden, müssen Sie immer ein paar Dinge beachten:
왘
Sie brauchen immer eine Session, um auf Daten zuzugreifen.
왘
Der Datenzugriff muss immer innerhalb einer Transaktion erfolgen.
왘
Wenn etwas schief geht, müssen Sie die Transaktion zurückrollen.
Schauen Sie sich den folgenden Quellcode an, lassen Sie ihn einfach mal durchlaufen und prüfen Sie, was in der Datenbank passiert.
In der Methode main rufen wir verschiedene Methoden auf, die Daten anlegen,
ändern, löschen oder anzeigen. Wenn in einer Methode eine Exception auftritt,
stellen wir sicher, dass unsere Transaktion zurückgerollt und die Hibernate-Session geschlossen wird.
package de.laliluna.example;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.hibernate.*;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
import de.laliluna.hibernate.InitSessionFactory;
public class TestExample {
private static Logger log = Logger.getLogger(TestExample.class);
public static void main(String[] args) {
try {
clean();
createHoney();
createRelation();
delete();
update();
query();
initBees();
} catch (RuntimeException e) {
try {
Session session = InitSessionFactory.getInstance()
.getCurrentSession();
30
635-0.book Seite 31 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
if (session.getTransaction().isActive())
session.getTransaction().rollback();
} catch (HibernateException e1) {
log.error("Error rolling back transaction");
}
// throw the exception again
throw e;
}
}
Die Methode createHoney legt ein neues Objekt an und speichert es durch den
Aufruf von session.save in der Datenbank.
private static Honey createHoney() {
Honey forestHoney = new Honey();
forestHoney.setName("forest honey");
forestHoney.setTaste("very sweet");
Session session = InitSessionFactory.getInstance()
.getCurrentSession();
Transaction tx = session.beginTransaction();
session.save(forestHoney);
tx.commit();
return forestHoney;
}
Die Methode update lässt ein Objekt erzeugen, ändert dann den Namen und
aktualisiert das geänderte Objekt mit session.update.
private static void update() {
Honey honey = createHoney();
Session session = InitSessionFactory.getInstance()
.getCurrentSession();
Transaction tx = session.beginTransaction();
honey.setName("Modern style");
session.update(honey);
tx.commit();
}
Die Methode delete erzeugt gleichfalls ein Objekt und löscht es mit dem Aufruf
von session.delete sofort wieder.
private static void delete() {
Honey honey = createHoney();
Transaction tx = null;
Session session = InitSessionFactory.getInstance()
.getCurrentSession();
31
1.1
635-0.book Seite 32 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
Transaction tx = session.beginTransaction();
session.delete(honey);
tx.commit();
}
Die Tabellen werden von der Methode clean gesäubert. Die Methode session.createQuery erzeugt eine Abfrage, die durch executeUpdate ausgeführt wird.
private static void clean() {
Session session = InitSessionFactory.getInstance()
.getCurrentSession();
Transaction tx = session.beginTransaction();
session.createQuery("delete from Bee").executeUpdate();
session.createQuery("delete from Honey").executeUpdate();
session.flush();
session.clear();
tx.commit();
}
Die Methode createRelation zeigt uns, wie man Objekte erzeugt und die Beziehung zwischen den Objekten setzt. In der Datenbank wird eine Fremdschlüsselbeziehung erstellt.
private static void createRelation() {
Session session = InitSessionFactory.getInstance()
.getCurrentSession();
Transaction tx = session.beginTransaction();
Honey honey = new Honey();
honey.setName("country honey");
honey.setTaste("Delicious");
session.save(honey);
Bee bee = new Bee("Sebastian");
session.save(bee);
/* Wir setzen die Beziehung auf BEIDEN Seiten */
bee.setHoney(honey);
honey.getBees().add(bee);
tx.commit();
}
Zum Schluss sehen wir ein einfaches Beispiel, wie Daten mit der Hibernate Query
Language (HQL) abgefragt werden. Die Abfrage wird wiederum mit session.createQuery erzeugt. Diesmal rufen wir aber die Methode list auf, da wir ein Ergebnis
erwarten.
32
635-0.book Seite 33 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
private static void query() {
Session session = InitSessionFactory.getInstance()
.getCurrentSession();
Transaction tx = session.beginTransaction();
List honeys = session.createQuery
("select h from Honey as h").list();
for (Iterator iter = honeys.iterator(); iter.hasNext();) {
Honey element = (Honey) iter.next();
log.debug(element);
}
tx.commit();
}
}
Das ging jetzt sehr schnell, aber Sie müssen nicht alles auf Anhieb im Detail verstehen.
Das sollten Sie gelernt haben
Erstellen einer Klasse, die gemappt werden soll. Wichtig waren ein parameterloser
Default-Konstruktor, Serializable Interface, eine hübsche toString-Methode.
왘
Einfaches Mapping
왘
Speichern und Löschen von Objekten
왘
Eine einfache Abfrage
Warum gibt es den Try- und Catch-Block?
왘
Manche Datenbanken halten Ressourcen offen, wenn eine Transaktion nicht mit
commit oder rollback beendet wird. Deswegen gibt es das rollback nach einer
Exception.
왘
Nach einer Exception ist die aktuelle Session unbrauchbar. Wir müssen diese
schließen. In dem Beispiel verwenden wir die Einstellung current_session_
context="thread". Dieser Sessionkontext stellt sicher, dass beim Aufruf von commit oder rollback die Session geschlossen wird. Sonst müssen wir die Methode
session.close() aufrufen.
왘
In einer normalen Anwendung reicht uns eine Stelle aus, die Transaktionen
zurückrollt und die Session – wenn erforderlich – schließt.
왘
Das könnten wir in einem Exception Handler von Struts, einem Interceptor von
MyFaces oder in einem Servletfilter vornehmen.
Unser Quellcode sieht also gewöhnlich einfach so aus:
Session session =
InitSessionFactory.getInstance().getCurrentSession();
Transaction tx = session.beginTransaction();
33
1.1
635-0.book Seite 34 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
session.save(honey);
tx.commit();
Müssen wir unsere Session nicht schließen?
Richtig, wir müssen eine Session immer schließen. Ich finde es praktisch, wenn die Session automatisch nach einem commit oder rollback geschlossen wird. Der currentSessionContext thread, den wir in der Hibernate-Konfiguration eingestellt haben, stellt
das für uns sicher. Wir brauchen daher nicht explizit ein session.close aufzurufen.
Deployment im JBoss Application-Server
Wenn Sie versuchen, dieses Beispiel oder eins der späteren im JBoss Application-Server zu deployen, können Sie auf Schwierigkeiten stoßen.
JBoss bringt von Haus aus bereits Hibernate mit. Leider führt das zu unerwartetem
Verhalten in den Beispielen, da ich in der Hibernate-Konfiguration festlege, wie sich
die Session verhalten soll, und innerhalb vom JBoss dies teilweise ignoriert wird.
Entweder verwenden Sie vorerst den Tomcat Application-Server bzw. eine andere
Servlet Engine oder Sie werfen bereits jetzt einen Blick in die Abschnitte 2.3.2 und
5.4, »JTA versus JDBC Transaktionen«.
1.1.9 MyEclipse Tools für die Hibernate-Entwicklung
Es gibt zahlreiche Tools für die Entwicklung von Hibernate. Ich verwende MyEclipse, ein Plugin für Eclipse.
MyEclipse wird von Genuitec angeboten: http://www.myeclipseide.com/. Ich
verwende es für die Entwicklung von Webanwendungen. Es bietet Unterstützung für Spring, Hibernate, EJB, Struts, MyFaces und ist gewöhnlich auf einem
recht aktuellen Stand.
Hibernate-Unterstützung aktivieren
Mit MyEclipse können Sie Webprojekte direkt anlegen. Klickt man im Package
View mit der rechten Maustaste auf ein Projekt, kann man die Hibernate-Unterstützung im Kontextmenü aktivieren.
Abbildung 1.3 Hibernate-Unterstützung im Kontextmenü aktivieren
34
635-0.book Seite 35 Montag, 6. August 2007 12:52 12
Erstes Hibernate-Beispiel
Mit Hilfe des Wizards kann man:
왘
Bibliotheken hinzufügen
왘
Hibernate-Konfiguration erstellen
왘
Session-Factory erzeugen lassen
Über den Wizard kann man auch ein Connection Profile anlegen. Es konfiguriert
eine Datenbankverbindung mit Datenbanktreiber, Benutzernamen und Dialekt.
Abbildung 1.4 Ein Connection Profile erzeugen
Reverse Engineering
Hibernate liefert eigene Tools zur Erzeugung von Mapping-Dateien und Klassen
auf Basis einer existierenden Datenbank. MyEclipse integriert solche Funktionen
elegant in Eclipse.
Wenn Sie ein Connection Profile angelegt haben, öffnen Sie jetzt den View DB
Browser (MyEclipse) (siehe Abbildung 1.5).
Öffnen Sie das eben erstellte Connection Profile (siehe Abbildung 1.6).
35
1.1
635-0.book Seite 36 Montag, 6. August 2007 12:52 12
1
Einführung in Hibernate
Abbildung 1.5 Der View DB Browser
Abbildung 1.6
Das Profil öffnen
Wählen Sie die Tabellen aus, aus denen Sie Klassen, Mapping und DAOs erzeugen möchten.
Der Wizard bietet Ihnen unterschiedliche Optionen, wie Sie die Tabellen erzeugen können. Probieren Sie einfach die Möglichkeiten aus.
36
635-0.book Seite 37 Montag, 6. August 2007 12:52 12
Hibernate-Grundlagen
Abbildung 1.7 Die Auswahl der Tabellen
Hinweis
DAOs (Data Access Objects), die Sie ebenfalls mit dem Wizard erzeugen können,
besprechen wir zu einem späteren Zeitpunkt.
1.1.10 Andere Tools für die Hibernate-Entwicklung
Die Entwicklungsumgebungen IntelliJ und Netbeans verfügen von Haus aus über
Hibernate-Tools. Auf den Webseiten von Hibernate können Sie sich ferner die
Hibernate Tools herunterladen. Das ist ein Plugin für Eclipse.
1.2
Hibernate-Grundlagen
Sie wissen bereits, dass Hibernate ein Object-Relation-Mapping Framework ist.
Da Hibernate sogar ein besonders mächtiges ORM Framework ist, bietet es eine
ganze Menge an Funktionen.
1.2.1 Leistungsfähige Mapping-Varianten
Ein Mapping muss nicht immer aus eine Klasse pro Tabelle bestehen. Wir können eine Vielzahl von objektorientierten Konzepten mit Hilfe der Mappings darstellen.
Im ersten Beispiel haben Sie eine Beziehung zwischen Klassen kennen gelernt.
Das entspricht in der Objektorientierung einer Assoziation. Mit Hibernate kön-
37
1.2
635-0.book Seite 285 Montag, 6. August 2007 12:52 12
In diesem Kapitel werden Sie lernen, wie Sie Hibernate in andere Technologien integrieren und Exceptions mit diesen Technologien behandeln. Ich
werde einige Fallstricke nennen, damit Sie möglichst wenig Schwierigkeiten bei der Integration haben werden.
5
Integration anderer Technologien
Spring ist ein wunderbares Framework, um die Geschäftslogikschicht zu implementieren. Es kann Hibernate auf elegante Weise integrieren. Spring können Sie
auf der Seite http://www.springframework.org/ herunterladen. Dieses Kapitel
setzt voraus, dass Sie das Spring Framework kennen, weil ich keine SpringGrundlagen erklären werde.
5.1 Hibernate und Spring
Die Dokumentation zu Spring stellt drei Alternativen vor. Ich halte eine von
ihnen für nicht sehr schön und werde daher nur zwei Möglichkeiten erläutern.
Beide Beispiele verwenden Spring in der Version 2 mit Annotations. Sie benötigen daher Java 5 oder aktueller. Wenn Sie Java 1.4 verwenden, müssen Sie das
Transaktionshandling anders konfigurieren. Das werde ich an entsprechender
Stelle erläutern.
5.1.1 Konfiguration
Sie haben drei Möglichkeiten der Konfiguration von Hibernate, wenn Sie Spring
verwenden:
왘
Verweis in der Spring-Konfiguration auf eine Hibernate-Konfigurationsdatei
왘
Vollständige Konfiguration von Hibernate in der Spring-Konfigurationsdatei
왘
Mischen der beiden Ansätze
Ich würde die letzte Möglichkeit empfehlen, weil einige Entwicklungsumgebungen Textvervollständigung für Hibernate-Einstellungen in der Hibernate-Konfigurationsdatei anbieten. Nachfolgende Abbildung zeigt das für Eclipse mit dem
MyEclipse-Plugin:
285
635-0.book Seite 286 Montag, 6. August 2007 12:52 12
5
Integration anderer Technologien
Abbildung 5.1
Textvervollständigung mit dem MyEclipse-Plugin
Eine Konfiguration in Spring umfasst eine Datenquelle und eine vom Spring Framework zur Verfügung gestellte Session-Factory. Es ist wichtig, dass wir diese
verwenden, sonst funktioniert die Integration nicht ordentlich und es können
Connection Leaks auftreten.
<bean id="datasource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl"
value="jdbc:postgresql://localhost:5432/learninghibernate" />
<property name="user" value="postgres" />
<property name="password" value="p" />
<property name="minPoolSize" value="2" />
<property name="maxPoolSize" value="4" />
</bean>
<bean id="hibernateSessionFactory"
class="org.springframework.orm.hibernate3.annotation.
AnnotationSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
Die Hibernate-Konfigurationsdatei ist sehr kurz und enthält keine Angaben zur
Datenquelle oder zum Verhalten der Session.
286
635-0.book Seite 287 Montag, 6. August 2007 12:52 12
Hibernate und Spring
<hibernate-configuration>
<session-factory>
<property name="dialect">
org.hibernate.dialect.PostgreSQLDialect
</property>
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="hbm2ddl.auto">none</property>
<mapping class="de.laliluna.example.domain.Hedgehog" />
<mapping class="de.laliluna.example.domain.WinterAddress" />
</session-factory>
</hibernate-configuration>
Problembereich
Sie sollten auf keinen Fall die Datenquelle in der Hibernate-Konfigurationsdatei festlegen. Wenn doch, bekommen Sie Probleme, sobald Sie die Transaktionssteuerung
von Spring verwenden.
Alternativ können Sie alle Einstellungen der Session-Factory vollständig in Spring
konfigurieren.
<bean id="hibernateSessionFactory"
class="org.springframework.orm.hibernate3.annotation.
AnnotationSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="annotatedClasses">
<list>
<value>de.laliluna.example.domain.Hedgehog</value>
<value>de.laliluna.example.domain.WinterAddress</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.hbm2ddl.auto=none
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.cache.provider_class=org.hibernate.cache
.EhCacheProvider
</value>
</property>
</bean>
Unser Beispiel hat eine Session-Factory gezeigt, die Annotations unterstützt.
Wenn Sie nur XML Mappings einsetzen, können Sie auch die Klasse org.springframework.orm.hibernate3.LocalSessionFactoryBean auswählen.
287
5.1
635-0.book Seite 288 Montag, 6. August 2007 12:52 12
5
Integration anderer Technologien
Warum keine Hibernate-Session-Factory?
Es wäre möglich, statt der Spring-Session-Factory unsere Hibernate-Session-Factory
aus den bisherigen Beispielen zu verwenden. Dann müssten wir auch eins der in
Abschnitt 2.3, »Session und Transaktionen«, vorgestellten Pattern verwenden.
Session session = factory.getCurrentSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
// do some work
tx.commit();
} catch (RuntimeException e) {
try {
if (tx != null)
tx.rollback();
} catch (HibernateException e1) {
log.error("Transaction roleback not succesful", e1);
}
throw e;
}
Spring bietet uns eine Möglichkeit, Transaktionen auf eine komfortablere Art zu steuern. Die Transaktionssteuerung ist übergreifend und kann eine Hibernate- und eine
JDBC-Transaktion einschließen. Auf diese elegante Möglichkeit verzichten wir, wenn
wir die Hibernate-Session-Factory verwenden.
Ich empfehle, lieber die Möglichkeiten von Spring zu verwenden. Dabei müssen Sie
aber auf die Nutzung der Hibernate-Transaktionssteuerung verzichten, sonst hat
Spring erhebliche Schwierigkeiten, Datenbankverbindungen und Hibernate-Sessions
freizugeben. Verwenden Sie also auf keinen Fall session.beginTransaction(), wenn Sie
sich für den »Spring Weg« entscheiden.
5.1.2 Verwendung des Spring Templates
In diesem Abschnitt werden wir die erste Möglichkeit kennen lernen, Spring und
Hibernate zu integrieren. Sie finden eine vollständige Implementierung im Projekt HibernateSpring (http://www.galileocomputing.de/978). Die Bibliotheken
können Sie von der Spring Framework-Webseite herunterladen. Sie benötigen
die Download-Version mit allen Abhängigkeiten. Das Beispielprojekt verwendet
die Bibliotheken:
왘
spring.jar
왘
aspectjrt.jar
왘
spring-aspects.jar
왘
aspectjweaver.jar
288
635-0.book Seite 289 Montag, 6. August 2007 12:52 12
Hibernate und Spring
Spring bietet für unterschiedliche Persistenztechnologien ein Template an, das
die Implementierung und technologiespezifische Exceptions kapselt und in einheitliche Spring Exceptions umwandelt. Diese Templates existieren für
왘
Hibernate
왘
JDO
왘
Ibatis
왘
Toplink
왘
JPA
왘
JDBC
Wenn Sie unterschiedliche Technologien verwenden, ist das Template ein guter
Ansatz, um ein einheitliches Verhalten und eine globale Transaktionssteuerung
zu erreichen.
Zunächst wird ein Hibernate Template erzeugt. Dieses benötigt die vorhin konfigurierte Spring-Session-Factory.
HibernateTemplate template = new HibernateTemplate(factory);
Das Template wird verwendet, um Hibernate zu kapseln. Das unten stehende
Beispiel zeigt die Verwendung. Sie lesen den Quellcode am besten von innen
nach außen.
return (List<Hedgehog>) template.execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
return session.createCriteria(Hedgehog.class).list();
}
});
Mit new HibernateCallback() erzeugen wir eine anonyme Implementierung des
Interfaces HibernateCallback. Das Interface hat genau eine Methode: doInHibernate. Die Methode bekommt von Spring als Parameter eine Hibernate-Session
übergeben. Die eigentliche Arbeit wird in der Zeile return session.get(Hedgehog.class, id) verrichtet.
Wir übergeben der Methode execute des Templates diese frisch erstellte Implementierung zur Ausführung.
Diese Konstruktion mag ungewöhnlich erscheinen, ermöglicht aber Spring, die
Ausführung des Hibernate-Codes zu kapseln, Ausnahmen umzuwandeln und
sicherzustellen, dass, wenn eine Exception im Hibernate-Code auftritt, die Trans-
289
5.1
635-0.book Seite 290 Montag, 6. August 2007 12:52 12
5
Integration anderer Technologien
aktion zurückgerollt und die Session geschlossen wird. Bisher mussten Sie das
immer selbst erledigen.
Der aufmerksame Leser wird sich jetzt vielleicht fragen, welche Transaktion
zurückgerollt wird. Schließlich haben wir keine Transaktion begonnen. Wenn
wir nicht explizit eine Transaktion festlegen, stellt Spring das Transaktionsverhalten der JDBC-Verbindung auf auto-commit. Jede Abfrage läuft dann in einer
Transaktion. Wie das Transaktionsverhalten explizit gesteuert wird, sehen wir
uns im übernächsten Abschnitt an.
Am Ende noch ein wichtiger Hinweis: Das Hibernate Template bietet für viele
Methoden der Hibernate-Session bereits eine fertige Implementierung: save,
saveOrUpdate, delete, update und viele mehr. Diese können Sie beruhigt verwenden.
template.save(hedgehog);
Problembereich des Hibernate Templates
Ich rate dringend davon ab, die unterschiedlichen find-Methoden des Hibernate
Templates zu verwenden. Das Template hat globale Einstellung für die maximale
Anzahl von Zeilen, die eine Abfrage zurückliefert, zum Verhalten in Bezug auf den
Cache und diversen anderen Parametern. So können Sie »interessante«, aber unerwartete Ergebnisse erhalten.
Schreiben Sie Ihre Abfragen lieber selbst und kapseln Sie diese, wie oben gezeigt, in
einem HibernateCallBack.
5.1.3 Alternative zum Spring Template
Es gibt sicherlich schöneren Quellcode als das oben gezeigte Template. Ich
möchte Ihnen daher eine Alternative zeigen, die auf dieses Konstrukt verzichtet.
Wir verwenden die Methode getCurrentSession, die uns auch in der Spring-Session-Factory zur Verfügung steht. Ähnlich wie bei der Verwendung eines CurrentSessionContext rufen wir diese Methode überall auf, wo wir eine HibernateSession benötigen.
protected Session getCurrentSession() {
return factory.getCurrentSession();
}
public void save(Hedgehog object) {
getCurrentSession().saveOrUpdate(object);
}
290
635-0.book Seite 291 Montag, 6. August 2007 12:52 12
Hibernate und Spring
Unser Quellcode funktioniert damit aber noch nicht. Bei diesem Ansatz müssen
wir explizit eine Transaktion vor dem Aufruf von getCurrentSession starten. Wie
das geht, zeige ich im nächsten Abschnitt.
Exception Handling
Die Spring-Dokumentation behauptet, dass wir durch diesen Ansatz statt mit einheitlichen Spring Exceptions mit Hibernate Exceptions umgehen müssen.
Das ist nicht sehr präzise ausgedrückt. Die Exception wird nur später umgewandelt.
Unser erster Ansatz mit Templates wandelt die Exception sofort im Template um. Der
zweite Ansatz wandelt die Exception erst im Rahmen der Transaktionssteuerung um.
Das bedeutet, dass die Methode in unserer Klasse HedgeHogServiceImp bereits abgearbeitet ist. Da Hibernate Exceptions gewöhnlich fatal sind und erst im FrontendLayer – zum Beispiel in der Webanwendung – behandelt werden, ist uns dieses Verhalten egal.
Der zweite Ansatz ist meiner Meinung nach eine gute Wahl, da er besser zu lesen ist
und weniger Schreibarbeit erfordert.
5.1.4 Transaktionssteuerung
Es ist sehr einfach, Transaktionen mit Spring zu steuern. In der Spring-Konfigurationsdatei müssen Sie nur einen Transaktionsmanager konfigurieren. In diesem
Beispiel verwenden wir einen JDBC-basierten Transaktionsmanager.
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager"
class="org.springframework.orm.hibernate3.
HibernateTransactionManager">
<property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>
Hinweise zur Konfiguration eines JTA-basierten Transaktionsmanagers finden
Sie in der Spring-Dokumentation. Die Konfiguration hängt immer vom Application-Server ab.
Innerhalb der Anwendung sind Transaktionen leicht zu integrieren. Wir müssen
nur die Annotation @Transactional vor eine Methode schreiben. Spring wird
dann vor der Methode die Transaktion starten und nach der Methode ein commit
aufrufen.
@Transactional(propagation = Propagation.REQUIRED)
public void update(Hedgehog hedgehog) {
hedgehogDao.update(hedgehog);
}
291
5.1
635-0.book Seite 292 Montag, 6. August 2007 12:52 12
5
Integration anderer Technologien
propagation legt die Art der Transaktion fest. Ich habe eine Übersicht über die
Transaktionsarten zusammengestellt.
Art der Transaktion
Verhalten
REQUIRED
Eine Transaktion ist erforderlich. Wenn keine Transaktion geöffnet ist, wird eine begonnen und nach der Methode abgeschlossen. Sonst läuft die Methode innerhalb der bestehenden Transaktion.
Diese Einstellung ist der Vorgabewert.
SUPPORTS
Transaktionen werden unterstützt, aber es wird keine Transaktion
gestartet. Wenn es eine gibt, läuft die Methode innerhalb der
Transaktion, wenn nicht, wird die Methode einfach so aufgerufen.
MANDATORY
Es ist eine Transaktion erforderlich, aber es wird keine gestartet.
Wenn es eine gibt, läuft die Methode innerhalb der Transaktion,
wenn nicht, wird eine Exception geworfen.
REQUIRES_NEW
Es ist eine Transaktion erforderlich und es wird immer eine neue
gestartet. Wenn es bereits eine gibt, wird diese pausiert. Nicht
alle Transaktionsmanager unterstützen diese Möglichkeit.
NOT_SUPPORTED
Die Methode kann nicht innerhalb einer Transaktion aufgerufen
werden. Wenn eine Transaktion existiert, wird diese pausiert.
Nicht alle Transaktionsmanager unterstützen diese Möglichkeit.
NEVER
Die Methode kann nicht innerhalb einer Transaktion aufgerufen
werden. Wenn eine Transaktion existiert, wird eine Exception
geworfen.
NESTED
Es wird eine verschachtelte Transaktion gestartet, also innerhalb
einer bestehenden Transaktion wird eine weitere gestartet. Sie
können den Transaktionsmanager DataSourceTransactionManager verwenden. Verschachtelte Transaktionen werden allerdings
nur von wenigen Datenbanken unterstützt. Manche JTA-Transaktionsmanager unterstützen gleichfalls JTA.
Wenn eine Exception vom Typ RuntimeException innerhalb der Methode auftritt, führt Spring automatisch ein Rollback der Transaktion durch. Das gilt nicht
für die so genannten Checked Exceptions. Das Rollback-Verhalten können Sie für
Checked Exceptions festlegen. Mehr Informationen dazu finden Sie in der
Spring-Dokumentation.
Tipp: Transaktionskonfiguration auf Klassenebene
Sie können die Annotation @Transactional auch vor die Klasse schreiben. Dann verwendet Spring für alle öffentlichen Methoden der Klasse eine Transaktion. Die Annotation auf Klassenebene ist eine Vorgabe für die Methoden. Wenn sich eine Methode
anders verhalten soll, so können Sie dort einfach eine weitere Annotation einfügen
und den Vorgabewert überschreiben.
292
635-0.book Seite 293 Montag, 6. August 2007 12:52 12
Hibernate und Struts
Transaktionen ohne Annotation
Die Verwendung von Annotations für die Konfiguration ist meiner Meinung nach
eine sehr schöne Lösung. Wenn Sie ein älteres JDK als Version 5 verwenden müssen,
stehen Ihnen Annotations leider nicht zur Verfügung.
In diesem Fall würde man die Transaktionen entweder explizit im Quellcode steuern
oder über die Spring-Konfigurationsdatei festlegen. Mehr Informationen dazu finden
Sie in der Spring-Dokumentation.
5.2 Hibernate und Struts
Ich habe eine kleine Beispielanwendung geschrieben, die Sie auf der Webseite
zum Buch (http://www.galileocomputing.de/978) finden. Diese Anwendung
orientiert sich an Best Practices und Sie können sie als hochwertige Vorlage verwenden. Das Projekt heißt Hibernatestruts. Die Anwendung setzt die Ajax-Technologie ein, zeigt eine Liste von Igeln und erlaubt, Igel zu erstellen und zu bearbeiten. Als Datenbank habe ich PostgreSQL eingesetzt.
Folgende Bibliotheken habe ich verwendet:
왘
Struts 1.3
왘
Displaytag 1.1 (http://displaytag.sourceforge.net/11/)
왘
Hibernate 3.2 Core und Annotation
왘
Ajaxtags 1.2 (http://ajaxtags.sourceforge.net/)
왘
Prototype Ajax 1.5.0 (http://www.prototypejs.org/)
왘
Script.aculo.us 1.7.0 (http://script.aculo.us/)
Die Anwendung demonstriert:
왘
Einsatz von Geschäfts- und DAO-Layer
왘
Verwendung einer generischen Dao-Implementierung
왘
Optimistisches Sperren
왘
Zentraler Umgang mit Exception
Ich werde die letzten beiden Punkte im Folgenden im Detail erklären.
5.2.1 Optimistisches Sperren
Optimistisches Sperren bedeutet, dass Hibernate prüft, ob ein anderer Benutzer
einen Datensatz bereits geändert hat, seitdem die Daten geladen worden sind.
293
5.2
635-0.book Seite 361 Montag, 6. August 2007 12:52 12
Index
<array> 203
<bag> 195
<cache> 160
<collection-id> 202
<component> 246
<composite-element> 248
<composite-id> 187, 239, 256
<discriminator> 264
<formula> 239
<generator class=foreign> 216
<idbag> 202
<join table=..> 272
<join> 227
<joined-subclass> 268
<list> 201
<many-to-any> 280
<many-to-many> 226, 229
<many-to-one> 211, 220
<map> 198
<map-key> 198
<meta-value> 280
<one-to-one> 214
<parent> 246
<primitive-array> 204
<set 218
<set> 193, 218
<subclass> 264, 272
<union-subclass> 277
<version 101
@AccessType 345
@AttributeOverride 330
@Basic 328
@BatchSize 117, 342
@Cache 347
@Cascade 338
@Check 347
@CollectionOfElements 203, 247, 252,
334
@Column 328
@ColumnResult 355
@DiscriminatorColumn 263, 344
@DiscriminatorFormula 345
@DiscriminatorValue 344
@Embeddable 245, 248, 334
@Embedded 245, 333
@EmbeddedId 184, 325
@Entity 24, 319
@EntityResult 354
@Enumerated 329
@Fetch 338
@FieldResult 354
@Filter 348
@FilterDef 349
@Filters 348
@Formula 331
@GeneratedValue 24, 324
@GenericGenerator 327
@Id 24, 324
@IdClass 186, 325
@Index 322
@IndexColumn 201, 247, 337
@Indexed Hinweis 222
@Inheritance 263, 267, 343
@JoinColumn 24, 335
@JoinColumns 335
@JoinTable 226, 228, 336
@LazyCollection 342
@LazyToOne 343
@Length 133
@Lob 135, 329
@ManyToMany 228, 333
@ManyToOne 24, 220, 332
@MapKey 198, 339
@MapKeyManyToMany 234
@MappedSuperclass 282, 345
@NamedNativeQueries 129, 352
@NamedNativeQuery 353
@NamedQueries 128, 350
@NamedQuery 128, 350–351
@NotFound 340
@OnDelete 340
@OneToMany 24, 218, 332
@OneToOne 210, 331
@OrderBy 341
@org.hibernate.annotations
AccessType 345
BatchSize 342
Cache 347
Cascade 338
Check 347
361
635-0.book Seite 362 Montag, 6. August 2007 12:52 12
Index
CollectionOfElements 334
DiscriminatorFormula 345
Entity 319
Fetch 338
Filter 348
FilterDef 349
Filters 348
Formula 331
GenericGenerator 327
Index 322
IndexColumn 337
LazyCollection 342
LazyToOne 343
MapKey 339
NamedQueries 350
NamedQuery 351
OnDelete 340
OrderBy 341
ParamDef 349
Parameter 347
Parent 334
Table 322
Type 346
TypeDef 347
TypeDefs 346
Where 341
@org.hibernate.NotFound 340
@ParamDef 349
@Parameter 347
@Parent 245, 334
@PersistenceContext 308
@PrimaryKeyJoinColumn 216, 336
@PrimaryKeyJoinColumns 337
@QueryHint 128, 351
@SecondaryTable 323
@SequenceGenerator 24, 325
@SqlResultSetMapping 129, 354
@SqlResultSetMappings 353
@Table 322
@TableGenerator 326
@Target 170
@Temporal 329
@TransactionAttribute 308
@Transient 328
@Type 346
@TypeDefs 130, 346–347
@UniqueConstraint 323
@Version 101, 330
@Where 341
362
A
Abfragen
@NamedQueries 128
@NamedQuery 128
AliasToBeanResultTransformer 109
all 113
any 113
createAlias 111
DetachedCriteria 113
executeUpdate 115
exists 113
gtAll 113
gtSome 114
in 113
left join fetch 118
MatchMode.START 110
Parameter 112
Property.forName 113
Restrictions.disjunction 111
Restrictions.eq 109
Restrictions.in 110
Restrictions.isEmpty 114
Restrictions.like 110
Restrictions.lt 111
Restrictions.or 111
setFetchMode 118
setParameterList 110
setReadOnly 108
some 113
uniqueResult 112
Where-Bedingung mit Beziehungen 111
abstract 176
action = NotFoundAction.IGNORE 340
after_statement 146
after_transaction 146
Aggregation 244
AliasToBeanResultTransformer 109
all 113
allocationSize 124, 325
Annotation 167
AnnotationConfiguration 29
Annotation-Nachteile 169
Annotations an Felder, Methoden und
Klassen 170
AnnotationSessionFactoryBean 286
Annotation-Vorteile 168
any 113
appliesTo = tableName 322
635-0.book Seite 363 Montag, 6. August 2007 12:52 12
Index
Architektur
Geschäftslogik 39
Persistenz Layer 39
Webanwendung 39
Array 190
ArrayList 189–190
Assoziation 17, 37, 188, 244
ASTQueryTranslatorFactory 152
auto-import 172
B
Bag 189
batch-size 175
Bibliotheken 27
Bidirektional 205
BinaryType 136
BLOB 134
BLOB Lazy Loading 126
Blob-Felder 149
BlobType 137
bytea 136
Bytecode-Instrumentation 126–127
C
C3P0 153
c3p0.* 145
Cache
Cache 157
Cache deaktivieren 149
Cache Modus 159
Cache verwenden 161
nonstrict-read-write 159
Query Cache 162
read-only 159
read-write 159
transactional 159–160
cache.provider_class 149
cache.query_cache_factory 149
cache.region_prefix 150
cache.use_minimal_puts 149
cache.use_query_cache 149
cache.use_second_level_cache 149
cache.use_structured_entries 150
CacheConcurrencyStrategy 348
CacheModeType 351
Cache-Regionen 150
Cascading 48, 207
all 208
all-delete-orphan 208
CascadeType 338
CascadeType.ALL 208
CascadeType.DELETE_ORPHAN 208
CascadeType.REFRESH 207
CascadeType.REMOVE 207
delete 208
delete-orphan 208
evict 208
Fehlerpotenzial 209
lock 208
MERGE 208
PERSIST 208
persist 208
REFRESH 208
refresh 208
REMOVE 208
replicate 208
save-update 208
catalog 172, 174
catalog = catalogName 322
cglib.use_reflection_optimizer 144, 152
check 176
class 173
ClassicQueryTranslatorFactory 152
clause = deleted=false 341
clear() 124
CLOB 126, 134
CLOB Lazy Loading 126
Clustering 149
Collection 189
Component Mapping 243
Configuration 29
Connection Pool
Connection Pool 152
Connection Pool mit Jboss 156
Connection Pool mit Tomcat 154
connection.autocommit 146
connection.datasource 145
connection.driver_class 145
connection.eineEinstellung 146
connection.isolation 146
connection.password 145
connection.provider_class 146
connection.release_mode 146
connection.url 23, 145
connection.username 145
context.xml 154
363
635-0.book Seite 364 Montag, 6. August 2007 12:52 12
Index
createAlias 111
createSQLQuery 115
Criteria Queries 39
Criteria.DISTINCT_ROOT_ENTITY 43
Criteria-Abfragen 104
current_session_context 33
current_session_context_class 147
D
DAO
DAO Factory 77
Dao mit SessionFactory vs Session 78
DAOs mit Generics 81
DAOs mit Java 1.4 84
Data Access Objects (DAO) 74
Kluge DAO 86
Datenbanktreiber 28
DBCP 153
Debugging 115
default_batch_fetch_size 118, 151
default_catalog 151
default_entity_mode 150
default_schema 150
default-access 172
default-cascade 172
default-lazy 172
DefaultLoadEventListener 132
DerbyDialect 23
detached 44
DetachedCriteria 113
dialect 22, 144
Discriminator Column 38
discriminatorType 263
discriminatorType = DiscriminatorType.STRING 344
DiscriminatorType.CHAR 344
DiscriminatorType.INTEGER 344
DiscriminatorType.STRING 263, 344
discriminator-value 173
dom4j 150
dynamic insert 129, 174, 320
dynamic update 101, 129, 174, 320
dynamic-map 150
E
EH Cache 164
EJB 3 301
364
Entity 167, 173
Entity-Manager 301
EntityManagerFactory 303
entity-name 176
EnumType.ORDINAL 329
EnumType.STRING 329
EventListener 132
Eventsystem 132
Exception 30, 89
LazyInitializationException 41, 94
NonUniqueObjectException 50
StaleObjectStateException 51
Exception Handling 68
Exception Handling in JPA 305
Exception Handling mit JSF (MyFaces)
296
Exception Handling mit Spring 292
Exception Handling mit Struts 294
Try und Catch 33
Try und Catch in Webanwendung 68
executeUpdate 115
exists 113
explicit 175
F
fetch=FetchType.EAGER 331
FetchMode.JOIN 339
FetchMode.SELECT 339
FetchMode.SUBSELECT 339
find 304
First Level Cache 87
First-Level-Cache 157
flush() 124
FlushMode 97
flushMode 351
FlushModeType.AUTO 351
Foreign Key Constraint 205
format_sql 116
Fremdschlüsselspalte 24
G
generate_statistics 151
GeneratedValue 168
GenerationType 168
GenerationType.AUTO 324
GenerationType.IDENTITY 324
GenerationType.SEQUENCE 324
635-0.book Seite 365 Montag, 6. August 2007 12:52 12
Index
GenerationType.TABLE 324
Generics 20
getReference 307
Glassfish 310
gtAll 113
gtSome 114
H
HashMap 190
HashSet 190
hbm2ddl.auto 22, 150
Hibernate Validator 133
hibernate.cfg.xml 143
hibernate.hbm2ddl.auto 29
Hibernate.initialize 43
hibernate.jdbc.use_streams_for_binary
144
hibernate.properties 143
hibernate3.jar 27
hibernate-annotations.jar 27
HibernateCallBack 290
hibernate-mapping 172
HibernateServiceBean 298
Hibernate-Typen 26
hints = {@QueryHint(...)} 350
HQL 32, 38, 103
HQL-, Criteria- und SQL-Vergleich 103
HSQLDialect 23
I
Id 168
<composite-id> 185
<generator class=native> 179
<id> 182
<key-property> 185
@EmbeddedId 184
@IdClass 186
assigned 178, 181
Composite Id 183
equals 183
foreign 182
GenerationType.AUTO 179
GenerationType.IDENTITY 180
GenerationType.SEQUENCE 179
GenerationType.TABLE 180
generator class 182
GenericGenerator 180
guid 181
hashCode 183
hilo 181
Id 176
identity 181
increment 182
künstlicher Schlüssel 178
MultipleHiLoPerTableGenerator 182
native 181
Natürliche Schlüssel 177
select 181
seqhilo 181
sequence 181
Trigger 181
unsaved-value 182
uuid 182
implicit 175
in 113
indexes 322
Inheritance 257
InheritanceType.JOINED 267, 343
InheritanceType.SINGLE_TABLE 263,
343
InheritanceType.TABLE_PER_CLASS 275,
343
initialValue=1 325
inner join 106
insert=false 206
InstrumentTask 127
Interceptor 131
inverse 206
inverseJoinColumns 228, 336
Inversion of Control 308
J
Java Persistence API 301
JavaServer Faces 295
Exception Handling 296
javax.persistence. 167
JBoss Application-Server 34
JBoss Cache 166
JBoss JPA 311
JBoss Treecache 166
jdbc.batch_size 148
jdbc.batch_versioned_data 148
jdbc.factory_class 148
jdbc.fetch_size 148
jdbc.use_get_generated_keys 149
365
635-0.book Seite 366 Montag, 6. August 2007 12:52 12
Index
jdbc.use_scrollable_resultset 148
jdbc.use_streams_for_binary 149
JDBCTransactionFactory 90
JDBC-Transaktionen 88
Jgroups 165
JNDI 154
JNDI Connection Pool 154
jndi.class 145
jndi.eineEinstellung 145
jndi.url 145
Join 106
joinColumns 228, 336
JPA 301
JPA und EJB3
@TransactionAttribute 308
Entity-Manager 301
EntityManager 304
EntityManagerFactory 303–304
find 304
getReference 307
Glassfish 310
Inversion of Control 308
JBoss 311
JPA 301
JPA – Java-Persistenz-API 171
persist 304
persistence.xml 302
Persistenz-Provider 302
remove 304
Toplink 301
TransactionAttributeType 308
MANDATORY 309
NEVER 309
NOT_SUPPORTED 309
REQUIRED 309
REQUIRES_NEW 309
SUPPORTS 309
JTA – Java Transaction API 88
jta.UserTransaction 148
K
Komponenten Mapping 243
Komposition 38, 244
Konfiguration
Konfiguration mit Java 144
Konkurrierender Zugriff 100
Konstruktor 20, 58
Konversationen 94
366
L
lazy 175
Lazy Initialization 40, 47
LazyCollectionOption.EXTRA 342
LazyCollectionOption.FALSE 342
LazyCollectionOption.TRUE 342
Lazy-Fetching 42
LazyInitializationException 41, 95
LazyToOneOption.FALSE 343
LazyToOneOption.NO_PROXY 343
LazyToOneOption.PROXY 343
left join fetch 43, 118
List 190
LoadEventListener 132
LOB (Large Object) 134
LocalSessionFactoryBean 287
LockMode.NONE 51
LockMode.READ 51
LockMode.UPGRADE 51, 103
Logging
log4j 29
log4j.logger.org.hibernate.cache 116
log4j.logger.org.hibernate.id 116
log4j.logger.org.hibernate.SQL 116
log4j.logger.org.hibernate.type 116
Löschen von Daten 53
Lucene 134
M
Map 190
mappedBy 206
Mapping
Beziehungen 187
Komponenten 243
Vererbung 257
Vor- und Nachteile 190
Mapping von Beziehungen
<array> 203
<bag> 195
<collection-id> 202
<idbag> 202
<join> 227
<list> 201
<many-to-many> 226, 229
<many-to-one> 211, 220
<map> 198
<map-key> 198
635-0.book Seite 367 Montag, 6. August 2007 12:52 12
Index
<one-to-one> 214
<primitive-array> 204
<set> 193, 218
@AttributeOverrides 197
@CollectionOfElements 197, 203
@Column 197
@IndexColumn 201, 203
@JoinColumn 192, 194, 197
@JoinTable 197, 226, 228
@ManyToMany 228
@ManyToOne 220
@MapKey 198
@MapKeyManyToMany 234
@OneToMany 192, 194, 201, 218
@OneToOne 210
@PrimaryKeyJoinColumn 216
@Sort 194
1:1 Beziehung 210
1:n-Beziehung 216
Array 191
Bag 190, 195
bidirektional 205
Fehlerpotenzial manyToMany 230
Foreign Key Constraint 205
insert=false 206
inverse 206
inverseJoinColumns 228
joinColumns 228
List 191
m:n-Beziehung 227
Map 191, 196
mappedBy 206
property-ref 214
rekursive Beziehung 236
Set 190, 192
SortedMap 191
SortedSet 190, 193
strategy = foreign 216
unidirektional 204
update=false 206
Verwalten der Beziehung 206
Vor- und Nachteile 190
Mapping von Komponenten
<component> 246
<composite-element> 248
<composite-id> 256
<parent> 246
@CollectionOfElements 247
@Embeddable 245
@Embedded 245
@Parent 245
einfache Komponente 244
Fehlerpotenzial bei non-indexed 249
Komponenten 243
Liste von Komponenten 247
Set von Komponenten 249
zusammengesetzte Primärschlüssel 254
Mapping von Vererbung
<discriminator> 264
<join table=..> 272
<joined-subclass> 268
<many-to-any> 280
<meta-value> 280
<subclass> 264, 272
<union-subclass> 277
@DiscriminatorColumn 263
@Inheritance 263
@MappedSuperclass 282
Auswahl des Mapping-Ansatzes 259
Discriminator Column 38
discriminatorType 263
DiscriminatorType.STRING 263
InheritanceType.JOINED 267
InheritanceType.SINGLE_TABLE 263
InheritanceType.TABLE_PER_CLASS 275
Klassenhierarchie in einer Tabelle 262
Klassenhierarchie mit einer Tabelle für jede
konkrete Klasse 274
Klassenhierarchie mit einer Tabelle pro
Klasse 266
Klassenhierarchie mit einer Tabelle pro
Klasse + Discriminator 271
Klassenhierarchie mit einer Tabelle pro
Unterklasse 279, 281
Vererbung 257
MatchMode.START 110
max_fetch_depth 151
mutable 173
mutable = true 320
MyFaces 295
MySQL5Dialect 23
N
name 173
Named Queries 128
node 176
NonUniqueObjectException 50, 95
367
635-0.book Seite 368 Montag, 6. August 2007 12:52 12
Index
NotFoundAction.EXCEPTION 340
NotFoundAction.IGNORE 340
O
Object-Relational-Mapping 13
oid 136
on_close 146
OnDeleteAction.CASCADE 340
OnDeleteAction.NO_ACTION 340
Open-Session-in-View 42, 96
optimisticLock 101, 175
OptimisticLockType.ALL 101, 321
OptimisticLockType.DIRTY 102, 321
OptimisticLockType.VERSION 321
Optimistisches Sperren
optimisticLock = OptimisticLockType.VERSION 321
optimistisches Sperren 100
Optimistisches Sperren mit JSF 296
oracle.sql.CLOB 139
OracleDialect 23
order_updates 151
OS Cache 165
P
package 173
Performance 115
persist 304
persistence.xml 302
persistent 44
Persistenz 14
Persistenz-Provider 302
persister 175
persister = customPersister 321
Pessimistisches Sperren 102
pkJoinColumns 323
pojo 150
polymorphism 175
polymorphism = PolymorphismType.IMPLICIT 321
Polymorphismus 257
Primärschlüssel 176
Projections 108
Projections.count 108
Projections.groupProperty 108
Projections.projectionList 108
Projections.property 108
368
Property.forName 113
PropertyAccessor 172, 183
property-ref 214
proxy 174
Q
query = fromComputerBook), 350
Query Cache 163
query.factory_class 152
query.substitutions 152
R
Read-Only-Mapping 120
referencedColumnName=id 335
remove 304
Restrictions.disjunction 111
Restrictions.eq 109
Restrictions.in 110
Restrictions.isEmpty 114
Restrictions.like 110
Restrictions.lt 111
Restrictions.or 111
ResultTransformer 43
Reverse Engineering 35
rollBack 89
rowid 176
S
SaveOrUpdateEventListener 132
schema 172–173
Scrollable Resultsets 148
ScrollableResults 122
ScrollMode.FORWARD_ONLY 122
Second-Level-Cache 157
select-before-update 174
selectBeforeUpdate = false 320
SequenceGenerator 168
sequenceName=dbSequenceName, 325
Serializable 20, 58
SerializableClob 139
Servletfilter 96
Session 28
Extended Session 97
First Level Cache 87
FlushMode 97
Kurze Lebensdauer 95
635-0.book Seite 369 Montag, 6. August 2007 12:52 12
Index
Lange Lebensdauer 97
Lange Lebensdauer mit JPA und EJB 3 99
Open-Session-in-View 96
Session schließen 34
session.beginTransaction 89
session.clear 124
session.close 89
session.createCriteria 106
session.createQuery 32, 105
session.createSQLQuery 115
session.delete 31, 53–54
session.delete bei Beziehungen 53
session.evict 55
session.flush 55, 88, 124
session.get 50, 53
session.getNamedQuery 128
session.getStatistics 122
session.load 307
session.lock 49–50
session.merge 49, 52
session.persist 307
session.refresh 55
session.save 31, 47
session.saveOrUpdate 52
session.update 31, 49, 51
Session-Lebensdauer 94
session.close 34
session_factory_name 147
SessionFactory
Beispiel 28
factory.openSession 89
getCurrentSession 90
HibernateSessionFactory 91
HibernateUtil 91
JBossTransactionManagerLookup 91
Sessionkontext 90
Set 190
setFetchMode 118
setParameterList 110
setProjection 108
setReadOnly 108
setResultTransformer 43
show_sql 150
skalare Werte 105
some 113
SortedMap 190
SortedSet 190
Spring
DataSourceTransactionManager 292
Exception Handling 291
HibernateCallBack 290
Konfiguration 285
Problembereich Transaktionssteuerung
287
Propagation.MANDATORY 292
Propagation.NESTED 292
Propagation.NEVER 292
Propagation.NOT_SUPPORTED 292
Propagation.REQUIRES_NEW 292
Propagation.SUPPORTS 292
Spring Templates 288
Transaktionssteuerung 291
Springframework
@Transactional 291
AnnotationSessionFactoryBean 286
HibernateTransactionManager 291
LocalSessionFactoryBean 287
Propagation.REQUIRED 291
SQL 104
SQLServerDialect 23
StaleObjectStateException 100
StandardQueryCache 162–163
Stored Procedures 125
Struts Framework
Exception Handling 294
optimistisches Sperren 293
Struts 293
subselect 176
Swarm Cache 165
SybaseDialect 23
T
Tabellen erstellen 29
Table 168, 173
targetElement = Country.class 340
targetEntity = Invoice1.class, 331
TemporalType.DATE 329
TemporalType.NONE 329
TemporalType.TIME 329
TemporalType.TIMESTAMP 329
ternary 233
thread 90
Thread local 90
ThreadLocalSessionContext 90
Tomcat JNDI 154
Tools
Eclipse 34
369
635-0.book Seite 370 Montag, 6. August 2007 12:52 12
Index
Hibernate Tools 37
IntelliJ 37
MyEclipse 34
Netbeans 37
WebTool-Plugin 58
transaction.auto_close_session 91, 93,
147
transaction.factory_class 147
transaction.flush_before_completion 93,
147
transaction.manager_lookup_class 147
TransactionAttributeType 308
MANDATORY 309
NEVER 309
NOT_SUPPORTED 309
REQUIRED 309
REQUIRES_NEW 309
SUPPORTS 309
Transaktionssteuerung 76, 80
transient 44
Treecache 166
TreeMap 190
TreeSet 190
type 26
U
Unidirektional 204
uniqueConstraints = { ...} 322
uniqueResult 112
UnsupportedOperationException 115
update=false 206
UpdateTimestampsCache 162
use_identifer_rollback 151
use_sql_comments 116, 151
V
ValidateEventListener 133
Validator 133
Vererbung 38, 257
Versionsspalte 100
W
where 175
370
X
XML Mapping
abstract 176
auto-import 172
batch-size 175
catalog 172, 174
check 176
class 173
default-access 172
default-cascade 172
default-lazy 172
discriminator-value 173
dynamic-insert 174
dynamic-update 174
entity-name 176
hibernate-mapping 172
lazy 175
mutable 173
name 173
node 176
optimistic-lock 175
package 173
persister 175
polymorphism 175
proxy 174
rowid 176
schema 172–173
select-before-update 174
subselect 176
table 173
where 175
XML Mapping 167
Herunterladen