Das Java – Eclipse -Maven – Hibernate – MySQL Beispiel

Ziel dieses Artikels ist es, ein einfaches Beispiel mit den oben genannten Technologien (Maven, Java, Hibernate und MySQL) zu realisiern, bei dem die Funktion und das Zusammenspiel der unterschiedlichen Komponenten deutlich wird.

Folgende Tools & Technologienverwende ich für dieses Beispiel:

Maven  (http://maven.apache.org/)

Eclipse (http://www.eclipse.org/)

Java (http://www.java.com/de/)

Hibernate (http://www.hibernate.org/)

MySQL  (http://www.mysql.de/)

Junit  (http://junit.org/)

 

Schritt 1: Tabelle anlagen

Als erstes wird in der MySQL Datenbank eine Tabelle angelegt. Auf diese Tabelle wird dann später mit Hibernate zugegriffen.

SQL Statement:

CREATE TABLE DBUSER (
  USER_ID       BIGINT (5)    NOT NULL,
  USERNAME      VARCHAR (20)  NOT NULL,
  CREATED_BY    VARCHAR (20)  NOT NULL,
  CREATED_DATE  DATE          NOT NULL,
  PRIMARY KEY ( USER_ID )
)

 

Schritt 2: Ein Java Projekt mit Maven anlegen

Um ein neues Projekt mit Maven anlegen zu können, muss maven installiert und konfiguriert sein. Details zur Installation und Konfiguration von MAven kann man unter (http://maven.apache.org/run-maven/index.html) finden.

Nach der Installation und Konfiguration von Maven kann man mit dem folgenden Aufruf ganz einfach ein neues Java Projekt erstellen.

mvn archetype:generate
-DgroupId=de.msoftware
-DartifactId=Example1
-DarchetypeArtifactId=maven-archetype-quickstart
-DinteractiveMode=false

 

Wenn man Maven das erste mal ausführt, warden eine ganze Menge jar Files heruntergeladen. Das passiert zum Glück nicht jedes Mal und wenn man Maven schon öfter mal genutzt hat, sieht man nun folgende Ausgaben auf der Konsole.

[INFO] Scanning for projects…
[INFO]                                                                        
[INFO] ————————————————————————
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ————————————————————————
[INFO]
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
[INFO]
[INFO] — maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom —
[INFO] Generating project in Batch mode
[INFO] —————————————————————————-
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0
[INFO] —————————————————————————-
[INFO] Parameter: groupId, Value: de.msoftware
[INFO] Parameter: packageName, Value: de.msoftware
[INFO] Parameter: package, Value: de.msoftware
[INFO] Parameter: artifactId, Value: Example1
[INFO] Parameter: basedir, Value: /home/user
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /home/user/Example1
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 1.552s
[INFO] Finished at: Mon Oct 08 16:40:58 CEST 2012
[INFO] Final Memory: 8M/23M
[INFO] ————————————————————————

 

Maven erstellt hier das sogenannte “Maven Standard Directory Layout” für das neue Java-Projekt. Dabei wählt Maven für den Name des Verzeichnisses den Namen, den man als “artifactId” Parameter beim Maven Aufruf mitgegeben hat.

Maven Standard Directory Layout

http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

Nun ist ein neuer Ordner mit dem Namen „Example1“ mit allen benötigten Projektdateien angelegt worden, der folgende Dateien enthält:

 

./pom.xml
./src
./src/test
./src/test/java
./src/test/java/de
./src/test/java/de/msoftware
./src/test/java/de/msoftware/AppTest.java
./src/main
./src/main/java
./src/main/java/de
./src/main/java/de/msoftware
./src/main/java/de/msoftware/App.java

 

Der Aufbau der Verzeichnisstruktur und die darin enthaltenen Dateien sollten dem geübten Java Entwickler nicht unbekannt sein. Einzig die Datei pom.xml ist neu. Die Datei enthält einige maven spezifisch Informationen, auf die ich später noch eingehen werde.

 

Schritt 3: Das Projekt in die Eclipse IDE importieren.

Für den Impot des Projektes in Eclipse hat Maven auch eine Lösung parat. Mit dem Aufruf mvn eclipse:eclipse kann man ein Projekt ganz einfach in Eclipse importieren. Wichtig ist, dass man sich beim Aufruf in dem Order befindet, in dem auch die pom.xml Datei liegt. In diesem Beispiel ist es der Ordner Example1.

Auch hier werden beim ersten Aufruf wieder eine ganze Menge Downloads gestartet. Spätestens beim 2ten Aufruf des Kommandos sollte auf der Konsole folgende Ausgabe erscheinen.

[INFO] Scanning for projects…
[INFO]                                                                         
[INFO] ————————————————————————
[INFO] Building Example1 1.0-SNAPSHOT
[INFO] ————————————————————————
[INFO]
[INFO] >>> maven-eclipse-plugin:2.9:eclipse (default-cli) @ Example1 >>>
[INFO]
[INFO] <<< maven-eclipse-plugin:2.9:eclipse (default-cli) @ Example1 <<<
[INFO]
[INFO] — maven-eclipse-plugin:2.9:eclipse (default-cli) @ Example1 —
[INFO] Using Eclipse Workspace: null
[INFO] Adding default classpath container: org.eclipse.jdt.launching.JRE_CONTAINER
[INFO] Not writing settings – defaults suffice
[INFO] File /home/user/Example1/.project already exists.
       Additional settings will be preserved, run mvn eclipse:clean if you want old settings to be removed.
[INFO] Wrote Eclipse project for “Example1″ to /home/user/Example1.
[INFO]
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 1.021s
[INFO] Finished at: Mon Oct 08 16:54:48 CEST 2012
[INFO] Final Memory: 5M/13M
[INFO] ————————————————————————

 

Nun hat sich die Verzeichnisstruktur etwas verändert. Hinzugekommen sind die beiden Eclipse typischen Dateien:

./.project
./.classpath

Nun kann man Eclipse öffnen und das Projekt über den Menüpunkt File -> Import -> „Existing Projects into Workspace“ importieren und schon erscheint in der Liste der Projekt, sofern man den Example1 Order im Workspace liegen hat. Wenn nicht, ist es jetzt der richtige Moment, den Ordner dorthin zu verschieben. Alternativ kann man auch Eclipse dazu nutzen, das Projekt in den Workspace zu kopieren. Dazu setzt man einfach das Häckchen „Copy projects into workspace“.

Nach dem Import erscheint direkt ein Fehler, der daher kommt, dass es Probleme mit jUnit gibt. Sieht man sich die Projekteigenschaften mal genauer an, kommt man schnell darauf. Die Bibliothek junit-3.8.1.jar konnte nicht geladen werden.  Das hat den einfachen Hintergrund, dass die junit Dateien nicht Teil des Projektes im Workspace sind, sondern direkt aus dem M2_REPO geladen werden. Daher muss Eclipse den Pfad des lokalen Maven Repositorys kennen. Um den Classpath so zu erweitern, dass auch die Dateien des M2_REPO Repositorys gefunden werden führt man einfach den folgenden Befehl  aus:

mvn -Declipse.workspace=/home/user/workspace eclipse:add-maven-repo

Danach muss Eclipse einman neu gestartet warden und schon sind die Fehler Vergangenheit. Der Aufruf erzeugt dabei auf der Konsole folgende Ausgaben.

[INFO] Scanning for projects…
[INFO]                                                                        
[INFO] ————————————————————————
[INFO] Building Example1 1.0-SNAPSHOT
[INFO] ————————————————————————
[INFO]
[INFO] — maven-eclipse-plugin:2.9:add-maven-repo (default-cli) @ Example1 —
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 1.492s
[INFO] Finished at: Tue Oct 09 08:07:47 CEST 2012
[INFO] Final Memory: 5M/13M
[INFO] ————————————————————————

 

Im Hintergrund passiert eigentlich nicht viel. Es wird nur in der Datei Example1/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs der Eintrag org.eclipse.jdt.core.classpathVariable.M2_REPO=/home/user/.m2/repository hinzugefügt. Damit hat Eclipse nun den Hinweis bekommen, die ClasspathVariable M2_REPO durch /home/user/.m2/repository zu ersetzen. Sieht man sich nun in den Projekteigenschaften den Java Build Path an, kann man bei der junit Bibliothek gut erkennen, dass Eclipse die Variable nun durch den Pfad ersetzt.

 

Schritt 4: Abhängigkeiten festlegen

Die ersten 3 Schritte haben nun ein fertiges, compilierbares, testbares und ausführbares „Hello Word“ Projekt erzeugt, das aber noch keinerlei Funktionalität enthält. Führt man in Eclipse die Funktion „Run“ aus, erhält man bei der Klasse App.java die Ausgabe „Hello World“ und bei AppTest.java wird eine jUnit Test ausgeführt, der einen Test enthält, der erfolgreich beendet wird.

So weit so gut. Nun soll die Anwendung aber ein wenig mehr tun, als nur ein ödes „Hello World“ auf den Montor zu  zaubern. Daher ist es nun nötig, sich über die verwendeten Bibliotheken Gedanken zu machen. Je nachdem, welche Anforderungen an ein Projekt gestellt werden, sollte man sich überlegen, was man davon selber programmiert oder ob es möglich ist, hier oder da eine Bibliothek zu verwenden. In diesem Beispiel werden folgende Bibliotheken verwendet:

-          junit (junit)
http://mvnrepository.com/artifact/junit/junit/4.10

-          mysql  (mysql-connector-java)
http://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.6

-          org.hibernate (hibernate-core)
http://mvnrepository.com/artifact/org.hibernate/hibernate-core/4.1.2

Da ich nun aber keine Lust habe, mich um die Bibliotheken und die Abhängigkeiten und das ganze Drumherum kümmern möchte, trage ich einfach die beiden Dependencies in meine pom.xml Datei ein. So entgehe ich der Dependency-Hell und kann mich ganz in Zukunft ganz auf meine Programmlogik konzentrieren. Eine gute Hilfe bietet mir hier die Seite http://mvnrepository.com. Hier kann ich einfach meine benötigte Bibliothek auswählen und kann dann den Dependency Block einfach per Drag and Drop in mein pom.xml File kopieren. Nach dem Kopieren der Textblöcke in den XML Source, empfiehlt es sich, einmal die Tastenkombination „Strg“ + „Shift“ + „F“ zu drücken. Damit wird der Sourcecode sauber formatiert und entspricht dann wieder den üblichen Formatierungs-Konventionen einer XML Datei.

Ob die Änderungen an der pom.xml Datei eine Auswirkung haben, kann man leicht testen, indem man auf der Konsole den Befehl „mvn package“ aufruft.Der Aufruf sollte mindestens folgende Aufrufe enthalten und einen Ordner target anlegen.

[INFO] Scanning for projects…
[INFO]                                                                        
[INFO] ————————————————————————
[INFO] Building Example1 1.0-SNAPSHOT
[INFO] ————————————————————————
[INFO]
[INFO] — maven-resources-plugin:2.5:resources (default-resources) @ Example1 —
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/user/workspace/Example1/src/main/resources
[INFO]
[INFO] — maven-compiler-plugin:2.3.2:compile (default-compile) @ Example1 —
[INFO] Nothing to compile – all classes are up to date
[INFO]
[INFO] — maven-resources-plugin:2.5:testResources (default-testResources) @ Example1 —
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/user/workspace/Example1/src/test/resources
[INFO]
[INFO] — maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ Example1 —
[INFO] Nothing to compile – all classes are up to date
[INFO]
[INFO] — maven-surefire-plugin:2.10:test (default-test) @ Example1 —
[INFO] Surefire report directory: /home/user/workspace/Example1/target/surefire-reports
 
——————————————————-
 T E S T S
——————————————————-
Running de.msoftware.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.062 sec
 
Results :
 
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
 
[INFO]
[INFO] — maven-jar-plugin:2.3.2:jar (default-jar) @ Example1 —
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 1.537s
[INFO] Finished at: Tue Oct 09 08:42:02 CEST 2012
[INFO] Final Memory: 4M/11M
[INFO] ————————————————————————

 

Wie man sieht, wird hier nicht nur das Jar File gebaut, sondern auch die junit Tests ausgeführt. Ist alles erfolgreich verlaufen, findet man man im Ordner target folgende Struktur vor:

target/
target/test-classes
target/test-classes/de
target/test-classes/de/msoftware
target/test-classes/de/msoftware/AppTest.class
target/classes
target/classes/de
target/classes/de/msoftware
target/classes/de/msoftware/App.class
target/surefire-reports
target/surefire-reports/TEST-de.msoftware.AppTest.xml
target/surefire-reports/de.msoftware.AppTest.txt
target/Example1-1.0-SNAPSHOT.jar
target/surefire
target/maven-archiver
target/maven-archiver/pom.properties

 

Ein Aufruf der Klasse App mit dem Aufruf „java -cp target/Example1-1.0-SNAPSHOT.jar de.msoftware.App“ erzeugt die folgende Ausgabe auf der Konsole.

Hello World!

Ein weiterer interessanter Aufruf von Maven ist „mvn site“. Mit dem Aufruf kann man unter target/site eine Reihe von html Dateien erzeugen lassen, die umfangreiche Informationen zu dem Projekt enthalten. Darunter auch die Dependencies, die in der Datei dependencies.html zu finden sind. In dem Dokument wird schnell deutlich, welche Abhängigkeiten man schon jetzt im Projekt hat.

Sehr interessant ist auch der Dependency Tree. In dem Tree werden noch einmal die Abhängigkeiten als Tree dargestellt. Zu jedem abhängigen Projekt wird hier auch die Projekt Lizenz angezeigt. So lässt sich auf einen Blick überschauen, ob Lizenzen dabei sind, die evtl. untereinander nicht kompatibel oder aus anderen Gründen nicht eingesetzt werden dürfen.

Schritt 5: Datenbank konfigurieren

Ein Hello Word zu erzeugen, ohne eine Zeile Programmcode schreiben zu müssen ist toll, aber jeder Entwickler weiß, dass heute zutage kaum eine Anwendung ohne eine Datenbank auskommt. Daher muss als nächstes die Konfiguration der Datenbank folgen.

In Schritt 1 wurde die Tabelle „DBUSER“ angelegt, die nun in unserem Java Projekt bekannt gemacht werden muss. Dazu wird eine Datei „DBUser.hbm.xml“ im Ordner src/main/resources/de/msoftware/user  mit folgendem Inhalt angelegt:

<?xml version=“1.0″ encoding=“utf-8″?>
<!DOCTYPE hibernate-mapping PUBLIC “-//Hibernate/Hibernate Mapping DTD 3.0//EN”
 ”http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd”>
<hibernate-mapping>
    <class name=“de.msoftware.user.DBUser” table=“DBUSER”>
        <id name=“userId” type=“int”>
            <column name=“USER_ID” precision=“5″ scale=“0″ />
            <generator class=“assigned” />
        </id>
        <property name=“username” type=“string”>
            <column name=“USERNAME” length=“20″ not-null=“true” />
        </property>
        <property name=“createdBy” type=“string”>
            <column name=“CREATED_BY” length=“20″ not-null=“true” />
        </property>
        <property name=“createdDate” type=“date”>
            <column name=“CREATED_DATE” length=“7″ not-null=“true” />
        </property>
    </class>
</hibernate-mapping>

In dieser Datei wird die Tabelle DBUSER über das Hibernate Mapping mit der Klasse com.msoftware.user.DBUser verbunden, die Id der DBUSER Tabelle festgelegt und die benötigen Spalten mit ihren Eigenschaften veröffentlicht. Dank des Mappings ist es nun sehr einfach, die zugehörige Klasse in Eclipse anzulegen. Im Ordner src/main/java/de/msoftware/user/ wird die Klasse DBUser mit folgendem Inhalt angelegt:

package de.msoftware.user;
 
import java.io.Serializable;
import java.util.Date;
 
public class DBUser implements Serializable {
 
            private static final long serialVersionUID = -7859213880449722708L;
           
            private int userId;
            private String username;
            private String createdBy;
            private Date createdDate;
 
            public DBUser() {
            }
 
            public DBUser(int userId, String username, String createdBy,
                                   Date createdDate) {
                        this.userId = userId;
                        this.username = username;
                        this.createdBy = createdBy;
                        this.createdDate = createdDate;
            }
 
}
 

Zum Anlegen der Getter und Setter für die Variablen verwenden wir eine der vielen hilfreichen Eclipse Werkzeuge. Dazu einfach im Sourcecode mit der rechten Maustaste (Sorry Mac-Users J ) das Kontextmenü öffnen und dort unter dem Menüpunkt „Source -> Generate Getters and Setters“ den Dialog zum Erzeugen von Gettern und Settern für die privaten Variablen aufrufen.

Nach der Auswahl der privaten Variablen kann man auf OK klicken und schon sind die get und set Methoden für die 4 Variablen erstellt.

Damit existiert nun eine Klasse, die per Hibernate Mapping mit einer Datenbank Tabelle verknüpft ist. Was nun noch fehlt ist die Datenbank Konfiguration, denn noch weiß die Anwendung noch nichts darüber, welche Datenbank verwendet werden soll. Hibernate benötigt also noch eine Konfigurationsdatei, in der die Eigenschaften der Datenbank eingetragen werden. Diese Datei wird im Ordern src/main/resources mit dem Namen hibernate.cfg.xml angelegt und hat folgenden Inhalt:

<?xml version=“1.0″ encoding=“utf-8″?>
<!DOCTYPE hibernate-configuration SYSTEM
    “classpath://org/hibernate/hibernate-configuration-3.0.dtd”>
    <hibernate-configuration>
            <session-factory>
                        <property name=“hibernate.connection.driver_class”>org.gjt.mm.mysql.Driver</property>
                        <property name=“hibernate.connection.url”>jdbc:mysql://localhost:3306/example_1</property>
                        <property name=“hibernate.connection.username”>root</property>
                        <property name=“hibernate.connection.password”>password</property>
                        <property name=“hibernate.dialect”>org.hibernate.dialect.MySQLDialect</property>
                        <property name=“hibernate.default_schema”>example_1</property>
                        <property name=“show_sql”>true</property>
                        <mapping resource=“de/msoftware/user/DBUser.hbm.xml”></mapping>
            </session-factory>
</hibernate-configuration>

Damit nun in der Anwendung auch ein Datenbank Verbindung hergestellt werden kann, muss auch noch eine Java Klasse erstellt werden, die einen einfachen Zugriff auf die Hibernate Sessions ermöglicht. Dazu wird unter src/main/java/de/msoftware/util eine neue Java Klasse mit dem Namen HibernateUtil mit dem folgenden Inhalt angelegt.

package de.msoftware.util;
 
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
 
public class HibernateUtil {
            private static SessionFactory sessionFactory = buildSessionFactory();
            private static ServiceRegistry serviceRegistry;
 
            private static SessionFactory buildSessionFactory() {
                        try {
                                   // Create the SessionFactory from hibernate.cfg.xml
                                   Configuration configuration = new Configuration();
                                   configuration.configure();
                                   serviceRegistry = new ServiceRegistryBuilder().applySettings(
                                                           configuration.getProperties()).buildServiceRegistry();
                                   sessionFactory = configuration.buildSessionFactory(serviceRegistry);
                                   return sessionFactory;
                        } catch (Throwable ex) {
                                   // Make sure you log the exception, as it might be swallowed
                                   System.err.println(“Initial SessionFactory creation failed.” + ex);
                                   throw new ExceptionInInitializerError(ex);
                        }
            }
 
            public static SessionFactory getSessionFactory() {
                        return sessionFactory;
            }
 
            public static void shutdown() {
                        // Close caches and connection pools
                        getSessionFactory().close();
            }
}

 

Die frisch erzeugte Klasse hat nun eine Menge Fehler, da Eclipse bisher nicht darüber informiert wurde, dass nun die hibernate jar Files benötigt werden. Dies kann man nun auf unterschiedliche Art und Weise lösen.

  1. Alles von Hand eintragen (Ist aber nicht zu empfehlen)
  2. m2eclipse installieren und dann unter “Configure” => “Convert to Maven Project” die Arbeit überlassen. Dies ist vermutlich der beste Weg, wenn man mit Eclipse arbeitet.
  3. Aufrufen von mvn eclipse:eclipse. Diese Variante ist nich ganz so elegant, wie m2eclipse, verdeutlicht aber, was Maven für Möglichkeiten bietet und in diesem Beispiel geht es ja auch darum. Maven zu versehen.

Nun wird also mit dem Aufruf „mvn eclipse:eclipse“ die .classpath Datei des Eclipse Projektes auf Basis der pom.xml angepasst und während die Datei vorher fast leer war, hat die Datei nach dem Maven Aufruf nun folgenden Inhalt:

<?xml version=”1.0″ encoding=”UTF-8″?>
<classpath>
  <classpathentry kind=”src” path=”src/test/java” output=”target/test-classes” including=”**/*.java”/>
  <classpathentry kind=”src” path=”src/main/java” including=”**/*.java”/>
  <classpathentry kind=”src” path=”src/main/resources” excluding=”**/*.java”/>
  <classpathentry kind=”output” path=”target/classes”/>
  <classpathentry kind=”con” path=”org.eclipse.jdt.launching.JRE_CONTAINER”/>
  <classpathentry kind=”var” path=”M2_REPO/junit/junit/4.10/junit-4.10.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/org/hamcrest/hamcrest-core/1.1/hamcrest-core-1.1.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/mysql/mysql-connector-java/5.1.6/mysql-connector-java-5.1.6.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/org/hibernate/hibernate-core/4.1.2/hibernate-core-4.1.2.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/antlr/antlr/2.7.7/antlr-2.7.7.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/org/jboss/logging/jboss-logging/3.1.0.GA/jboss-logging-3.1.0.GA.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/org/jboss/spec/javax/transaction/jboss-transaction-api_1.1_spec/1.0.0.Final/jboss-transaction-api_1.1_spec-1.0.0.Final.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/org/javassist/javassist/3.15.0-GA/javassist-3.15.0-GA.jar”/>
  <classpathentry kind=”var” path=”M2_REPO/org/hibernate/common/hibernate-commons-annotations/4.0.1.Final/hibernate-commons-annotations-4.0.1.Final.jar”/>
</classpath>

 

Alle Einträge die mit der ClasspathVariable M2_REPO beginnen, wurden von Maven hinzugefügt und sind nach einem Neustart von Eclipse im Java Build Path verfügbar. Damit steht nun eine Datenbankverbindung zur Verfügung und die Nutzung der Tabelle DBUSERS über die Klasse DBUsers aus der Anwendung heraus kann realisiert werden.

Schritt 6: Applikationslogik und Testen

Jetzt folgt der letzte Schritt, bei dem die Anwendung über die Anwendungslogik mit der Datenbank verbunden werden muss. Dazu wird die main Methode der App Klasse wie folgt ergänzt und die benötigten Imports mit Hilfe der Eclipse „Quick fixes“ ergänzt.

package de.msoftware;
 
import java.util.Date;
import org.hibernate.Session;
import de.msoftware.user.DBUser;
import de.msoftware.util.HibernateUtil;
 
public class App {
            public static void main(String[] args) {
                        System.out.println(“Maven + Hibernate + MySQL”);
                        App app = new App();
                        app.execute ();
            }
 
            private void execute() {
                        Session session = HibernateUtil.getSessionFactory().openSession();
 
                        session.beginTransaction();
                        DBUser user = new DBUser();
 
                        user.setUserId(1);
                        user.setUsername(“michael”);
                        user.setCreatedBy(“App”);
                        user.setCreatedDate(new Date());
 
                        session.save(user);
                        session.getTransaction().commit();
            }
}

 

Das Ausführen der App erzeugt nun in der Datenbank einen neuen Eintrag in der Tabelle DBUSER mit der ID = 1. Spätestens beim Zweiten Aufruf bekommt man dann aber den folgenden Fehler.

Exception in thread “main” org.hibernate.exception.ConstraintViolationException: Duplicate entry ’1′ for key ‘PRIMARY’

Das liegt einfach daran, dass schon ein Eintrag in der Datenbank vorhanden ist, der die ID 1 besitzt und die Spalte in der Datenbank als Primary Key gekennzeichnet ist. Daher kann man die execute Methode so wie sie ist nicht in den JUnit Test einfügen. Um einen sinnvollen Test der App Methode machen zu können, benötigt man im Idealfall als erstes also eine leere Datenbank, fügt dann einen Datensatz in die Datenbank ein und prüft zum Schluss, ob der Eintrag wirklich vorhanden ist.

Um der Anwendung ein wenig mehr Logik zu geben, wird die Klasse App noch einmal refactored und die Methoden getUser, saveUser und deleteUser in eine Klasse User ausgelagert. In der main Methode der App Klasse werden dann nur noch die Methoden aufgerufen.

Die Klasse User sieht dann z.B. wie folgt aus:

package de.msoftware.user;
 
import java.util.Date;
import org.hibernate.Session;
import de.msoftware.util.HibernateUtil;
 
public class User {
 
            Session session;
           
            public User ()
            {
                        session = HibernateUtil.getSessionFactory().openSession();
            }
           
            public DBUser getUser (int id)
            {
                        session.clear();
                        session.beginTransaction();
                        DBUser user = new DBUser();
                        session.load(user, id);
                        session.getTransaction().commit();
                        return user;
            }
           
            public void saveUser (int id, String username, String createdBy)
            {
                        session.clear();
                        session.beginTransaction();
                        DBUser user = new DBUser();
                        user.setUserId(id);
                        user.setUsername(username);
                        user.setCreatedBy(createdBy);
                        user.setCreatedDate(new Date());
                        session.save(user);
                        session.getTransaction().commit();
            }
           
            public void deleteUser (int id)
            {
                        session.clear();
                        session.beginTransaction();
                        DBUser user = new DBUser();
                        user.setUserId(id);
                        session.delete(user);
                        session.getTransaction().commit();
            }
}

 

Die Klasse App und den dazu gehörenden JUnit test kann man nun getrost löschen. Für den Test der Klasse User erzeugt man einen neuen JUnit Test mit der Eclipse Funktion „New JUnit Test Case“ und wählt hier für „Class under test“ die Klasse „de.msoftware.user.User“. In der Klasse UserTest wird dann ein Test mit einer Before und einer After Annotationen erstellt, der wie folgt aussieht.

package de.msoftware;
 
import static org.junit.Assert.*;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import de.msoftware.user.DBUser;
import de.msoftware.user.User;
 
public class UserTest {
                User user = new User ();
                private int id = 1;
                private String username = “michael”;
                private String createdBy = “App”;
 
                @Test
                public void testGetUser() {
                              
                               DBUser dbuser = user.getUser (id);
                               if (!dbuser.getUsername().equals(username))
                               {
                                               fail(“GetUser faild”);
                               }
                }
 
                @Before
                public void createUser() {
                               user.saveUser (id, username, createdBy);
                }
 
                @After
                public void deleteUser() {
                               user.deleteUser (id);
                }
 
}

 

Der Test legt vor dem Test der Methode getUser einen neuen Datensatz an und nach dem Test wird dieser Datensatz wieder gelöscht. Der Test selbst, prüft nur, ob der username des geladenen Obketes dem erwarteten username entspricht. Ist das der Fall, ist der Test erfolgreich.

 

Schritt 7: Packen

Nachdem nun alle Komponenten realisiert wurden und die Tests erfolgreich abgeschlossen sind, kann das Projekt zu einem Jar File gepackt werden. Dazu wird noch einmal der Befehl mvn package auf der Konsole eingegeben. Danach ist im Ordner target ein aktuelles Release der Anwendung ohne die Tests in der Datei Example1-1.0-SNAPSHOT.jar enthalten.

Hinweis: Der Dateiname setzt sich aus 2 Tags der pom.xml Datei zusammen. Einmal die artifactId (Example1) und dann noch die Version (1.0-SNAPSHOT). Das Maven hier ein Jar File erstellt wird auch in der pom.xml Datei festgelegt. In dem Tag packaging kann man statt jar z.B. auch war (für WAR-File J ) eintragen.

Weitere Details zur pom.xml kann man unter http://maven.apache.org/pom.html nachlesen.

Fazit

Jedem sollten nun die Zusammenhänge zwischen den eingesetzten Tools und Techniken klar sein. Trotzdem hier noch mal eine kurze Beschreibung der einzelnen Komponenten dieses Examples.

Java ist die Programmiersprache. Wer es geschafft hat das Beispiel durchzuarbeiten ohne Vorkenntnisse in Java zu haben verdient meinen Respekt. Alle anderen wissen was Java ist und ich brauche hier nicht weiter darauf eingehen.

Eclipse ist eine IDE zur Entwicklung von Software. Die Ursprünge von Eclipse liegen in der  Programmiersprache Java. Aber Eclipse wird mittlerweile auch für viele andere Programmiersprachen und Aufgaben eingesetzt. Eclipse selbst ist in Java realisiert und kann über Plugins beliebig erweitert werden.

Maven ist ein Build-Management-Tool für Java. Mit Maven kann man Java-Programme standardisiert erstellen und verwalten. Die Konfiguration erfolgt im wesentlichen in der pom.xml und auf der Konsole hat man einige Befehle, die Abläufe automatisieren können.

Hibernate ist ein Java Framework mit dem es sehr einfach möglich ist, Objete aus einem Java Programm  in einer relationalen Datenbank abzulegen. Dem Java-Programm erscheint die Datenbank dann als objektorientierte Datenbank, wodurch die Programmierung erleichtert wird.

MySQL ist sehr weit verbreitete relationalen Datenbank, die (auch) als Open-Source-Software verfügbar ist. MySQL ist heute in fast jedem Webhosting Paket verfügbar und wird oft in Zusammenhang mit PHP genannt. Es gibt aber Konrektoren für die meisten Programmiersprachen wir z.B. Java.

 

Weiterführende Themen:

  1. Java vs. PHP
  2. Mobile Games – Spieleprogrammierung für Handys mit Java ME von Thomas Lucka
  3. Oracle verklagt Google wegen Java in Android
  4. MySQL “ERROR 2006 (HY000) at line 270: MySQL server has gone away”
  5. Mobile Games – Spieleprogrammierung für Handys mit Java ME von Thomas Lucka
"));