Java: Hibernate Annotations @ManyToMany, @ManyToOne und @OneToMany

Wie bereits vor geraumer Zeit angekündigt, wollte ich Euch ja einen Beiträg zu den Annotations bzgl. Verbindung von zwei Entities nachreichen. Also gehen wir's an...

Diese Annotations benötigt Ihr, um zwischen mehren Entities eine Beziehung herzustellen. Grob gesehen erklären sie sich auch schon von selbst denn:

@ManyToMany: Stellt eine bidirektionale Beziehung zwischen zwei Entities her. D.h. man kann von beiden auf die jeweils andere kommen.
@ManyToOne: Stellt eine unidirektionale Beziehung zwischen zwei Entities her.
@OneToMany: Stellt eine unidirektionale Beziehung zwischen zwei Entities her.

Es gibt viele und komplizierte Konfigurationsmöglichkeiten um diese Annotations zu nutzen.

Ach Leute. Irgendwie steig ich da selbst auch nie durch und muss die Annotations per Ausprobieren richtig konfigurieren.
Sehr hilfreich ist die Seite Vaannila.com

Dort ist es besser erklärt als ich es machen könnte. Tut mir Leid Leute :-)

VN:F [1.9.1_1087]
Rating: 5.5/10 (2 votes cast)

Java: First Contact with Hibernate

Ich wurde von meinem Kollegen Basti (sein Blog) gebeten, ein kleines Tutorial zum Umgang mit Hibernate zu schreiben.

Ich werde jetzt also kurz zusammenfassen, wie Ihr eine Entity deklariert und diese dann in einer MySQL Datenbank abspeichert.

Für das Arbeiten mit Hibernate ist es notwendig einige Libraries zu nutzen. In dem Download am ende des Betrags sind diese Librarys enthalten.

Also erstes braucht Ihr eine SessionFactory. Die SessionFactory dient dazu, eine Schnittstelle zwischen Datenbank und "Euch" herzustellen. Diese Factory habe ich in unserem kleinen Beispiel HibernateSessionFactory genannt.

package de.skybreaker.factories;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

/**
* @author jst
* @date 18.03.2010
* @time 08:28:57
*/
public class HibernateSessionFactory {

    private static final SessionFactory sessionFactory;

    static {
        try {
            sessionFactory = new AnnotationConfiguration().configure()
                          .buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

     public static Session getSession() throws HibernateException {
         return sessionFactory.openSession();
     }
}

Diese SessionFactory wird aus der hibernate.cfg.xml zusammen gesetzt. Da wir hier Hibernate mit Annotations benutzen möchten, machen wir hier also :

new Annotation.Configuration().configure().buildSessionFactory()

Da wir keinen Pfad zur Konfigurationsdatei angeben sucht sich die Applikation den Konfiguration aus dem Rootverzeichnis des Projektes raus.

Kommen wir also zur Hibernatekonfiguration selbst. Diese wird in einer XML vorgenommen welche immer wie folgt starten muss:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

Hier müssen jetzt die Einstellungen "an" der SessionFactory vorgenommen werden.

<session-factory>
	<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
	<property name="connection.url">jdbc:mysql://localhost/tutorial</property>
	<property name="connection.username">tut</property>
	<property name="connection.password">tutorial</property>

        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
 	<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
        <property name="current_session_context_class">thread</property>
        <property name="hibernate.show_sql">false</property>
	<property name="hibernate.hbm2ddl.auto">update</property>

Im oberen Teil wird die Verbindung zur Datenbank deklariert. In meinem Bespiel wird eine MySQL-Datenbank benutzt. Die Datenbank heißt "tutorial" und ist mit dem Benutzer "tut" und Passwort "tutorial" erreichbar.
Über "connection.driver_class" muss der korrekte Datenbanktreiber übergeben werden. Ähnlich wie bei JDBC das:

Class.forName(com.mysql.jdbc.Driver);

Das Property "dialect" macht Hibernate quasi bekannt, welche Sprache es sprechen muss, damit die Datenbank es versteht. Hier wurde jetzt der "dialect" auf MySQLDialect gesetzt. Da wir ja hier einen MySQL-Datenbank benutzen. In "org.hibernate.dialect" sind noch diverse anderen Dialekte zu finden.
"hibernate.show_sql" kann zu Debug zwecken auf "true" gesetzt werden und bewirkt dann, wie der Parameter schon sagt, dass die SQL-Statements angezeigt werden.

Bei "hibernate.hbm2ddl.auto" ist es Wichtig, dass dieser Wert auf "update" gesetzt ist. Dieser Parameter dient dazu, zu kontrollieren, ob es zu einer Entity schon eine Tabelle gibt oder nicht. Falls nicht, wird eine neue Tabelle in der Datenbank entsprechend Ihrer Annotations angelegt. Wenn diese Tabelle existiert wird überprüft, ob sich etwas an der Entity geändert hat und die Tabelle angepasst. (Wäre z.B. ein Wert dazu gekommen)

        <mapping class="de.skybreaker.database.entities.Schueler" />
	<mapping class="de.skybreaker.database.entities.Klasse" />
</session-factory>
</hibernate-configuration>

An dieser Stellt gibt man mittels "
" die Klassen an, in welchen wir Annotations geschrieben haben die mit Hibernate behandelt werden sollen.

Eine annotierte Klasse sieht im Prinzip wie folgt aus:

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 * @author jst
 * @date 18.03.2010
 * @time 08:40:29
 */
@Entity
@Table(name = "schueler")
public class Schueler implements Serializable {

	private static final long serialVersionUID = 853018580018215819L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	@Column(nullable = false)
	private String vorname;

	@Column(nullable = false)
	private String nachname;

	@ManyToOne
	@JoinColumn(name = "klasse_id", nullable = true)
	private Klasse klasse;

	public Schueler() {

	}
...

Die Annotation @Entity gibt zunächst an, dass diese Klasse eine Datenbank-Entity wird bzw. ist. Dadurch wird hierfür schon mal eine Tabelle angelegt. Gibt man die Annotation @Table(name...) nicht an, so wird die Tabelle mit dem Klassen nahmen angelegt.

@Id deklariert, dass dies ein Primary Key in der Datenbanktabelle wird und macht es damit auch automatisch zum Pflicht Wert. Mit @GeneratedValue setzen wir fest, dass wir diesen Wert nicht Pflegen brauchen. Die Datenbank wird das in diesen Einstellungen für uns übernehmen.

@Column bewirkt ähnliches wie die Annotation @Table. Wir können hiermit einen alternativen Namen für diese Spalte setzen sowie mit "nullable" bestimmen, ob es Pflichtfelder sind oder nicht.
Außerdem ist es möglich Verbindungen zu anderen Klassen herzustellen. Hierfür benötigt man die Annotations @ManyToOne, @OneToMany oder @ManyToMany.
Das Annotieren mit diesen drei Annotations ist allerdings sehr komplex. Ich werde darauf vermutlich in einem weiteren Eintrag eingehen. Es sei jeden falls jetzt soviel gesagt, dass wir hier eine Verbindung zu Entity bzw. Klasse "Klasse" aufbauen und diese Verbindung über ein Idfeld "klasse_id" im Schueler festgehalten wird.

Die annotierten Klassen müssen auch über die Getter- und Setter-Methoden verfügen. Allgemein ist bekannt, dass Entity Klassen nach dem guten alten POJO Prinzip aufgebaut sein müssen. D.h. einen Entity Klasse soll bzw. darf nur die Getter- und Setter-Methoden, einen Standartkonstruktor und die toString/equals/etc. Methoden haben.

Das ist allerdings Bereits überholt. Man kann soviel Logik in eine Entity Klasse pumpen wie man möchte. Und es ist auch durch aus möglich einen Konstruktor mit Parametern zu erstellen und diesen zu nutzen. Das spart einem später dann viel Zeit und Arbeit beim erstellen der Objekte, da die Werte sofort gesetzt werden können und nicht über die Setter-Methoden befüllt werden müssen.

Ich hoffe, dass Euch diese schnelle Einleitung in Hibernate weitergeholfen hat. Ihr könnt euch hier ein kleines Beispiel Projekt runterladen.

Es folgen noch weitere Einträge zum Thema Hibernate

VN:F [1.9.1_1087]
Rating: 10.0/10 (1 vote cast)

Hallo Welt!

Endlich funktioniert der WordPress-Blog auch bei mir.... Wie hab ich's angestellt!? Keine Ahnung. Der Serverwechsel war wahrscheinlich ausschlaggebend.

Hetzner bietet mir jetzt ein neues Zuhause mit einem Dedizierten Root-Server.

Drückt mir die Daumen, dass ich es schaffe den Blog weiterzuführen und ich mit dem Server gut klar komme.

Euer Jörn

VN:F [1.9.1_1087]
Rating: 10.0/10 (1 vote cast)