Serialisierung von Java Objekten mit Hibernate II
Heute will ich noch kurz auf die Deserialisierung der Objekte eingehen, die wir im 1. Teil des Tutorials in die Datenbank geschrieben haben, eingehen. In diesem kurzen Abschnit will ich aber nur kurz darauf eingehen, wie man ein einzelnes Objekt, dessen Primary Key bekannt ist, aus der Datenbank auslesen kann.
Auf mehrere Objekte, und Querries werde ich in einem späteren Artikel gesondert eingehen.
Sämtlichen Schritte und nötige Anweisungen hierfür können dem Stück Code entnommen werden, genauere Erläuterungen dazu befinden sich in den jeweiligen Kommentaren.
package hibernate.tutorial; import de.blogd.tutorials.hibernate.MyObject; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.classic.Session; /** * Beispiel zur Deserialisierung eines Objekts aus der Datenbank * @author Stefan */ public class Deserialisierung { private static SessionFactory mySessionFactory; /** * Singleton zur Rückgabe einer aktuellen Session. * @return SessionFactgory */ public static SessionFactory getSessionFactory() { if (mySessionFactory == null) { mySessionFactory = new Configuration().configure().buildSessionFactory(); } return mySessionFactory; } /** * Erzeugt neue Session mit Hilfe der Session Factory * @return Session */ public static Session getSession() { return getSessionFactory().openSession(); } public static void main(String[] args) { /** * Auch für das deserialisieren von Objekten benötigen wir eine * Session, diesen können wir mit den, im letzten Tutorial erstellten, * Methoden bekommen. * Auch dies erleden wir wieder in einer Transaktion! */ Session myDeserialSession = getSession(); /** * Transaktion erstellen und Transaktion starten, in dieser können * die Objekte dann aus der Datenbank geholt werden. * Transaktion ist nicht zwenigend nötig, aber für ein sauberes Arbeiten * im Transaktionsbetrieb immer zu empfehlen. */ Transaction myDeserialTransaction = myDeserialSession.getTransaction(); myDeserialSession.beginTransaction(); /** * Nun holen wir das Objekt aus der Datenbank, hierzu nutzen wir einfach * die get() Methode der vorher angelegten Session, diese will 2 Parameter * 1. die zu deserialisierende Klasse, und 2. den Primärschlüssel des zu * deserialisierenden Objekts. * Als Rückgabewert erhält man ein Object, nach einem (erfolgreichen) cast * auf MyObject, kann mit diesem Objekt gearbeitet werden. */ MyObject myDeserialSampleObject = (MyObject) myDeserialSession.get(MyObject.class, 1); /** * Transaktion mit einem Commit abschließen, auch wenn keine Änderungen * gemacht wurden. */ myDeserialTransaction.commit(); /** * Nach Abschluss die Session wieder schließen. */ myDeserialSession.close(); } }
Serialisierung von Java Objekten mit Hibernate
Seit einigen Tagen plagte mich bei einem, von mir Privat getriebenen, Projekt das Problem, erzeugte Objekte in eine Datenbank zu schreiben. Zwar gibt es die Möglichkeit, hier einfach von Hand die entsprechende Engine zu schreiben, um die Attribute in die Datenbank zu schreiben, dies ist aber wie ich finde sehr aufwändig und fehleranfällig. Hibernate war mir aus diesem Kontext schon aus Java EE bekannt, womit sich dieses Framework förmlich aufgedrängt hat.
Hier will ich anhand eines kurzen Beispiel kurz demonstrieren, wie leicht eine Persistierung von Java Objekten in eine Datenbank ist, im Beispiel verwende ich MySql, eine Portierung ist aber nahezu problemlos auf andere Datenbanken wie Oracle, HSQLDB etc. möglich, hierzu müssen nur die entsprechenden Parameter in der Config Datei gesetzt werden und die entsprechenden Treiber in den Buildpath des Projekts eingebunden werden.
Die Konfiguration des MySQL Servers setze ich in dieser Einführung einfach mal vorraus, falls dies noch nicht geschehen ist, bietet sich die Installation von XAMPP an.
Der hier gezeigte Lösungsweg ist nur ein möglicher Weg, es gibt noch viele andere Varianten. Ich habe mich aber aufgrund der leichtesten Implementierung und Verständlichkeit zum
Demonstrieren dieses Weges entschlossen.
Am Anfang sollte man sich als erstes die benötigten Libaries etc. besorgen und in den Buildpath des Java Projekts einzubinden:
- Hibernate (http://www.hibernate.org/)
- dom4j (http://dom4j.sourceforge.net/)
- SLF4J (http://www.slf4j.org/)
- MySQL Connector (http://www.mysql.com/downloads/connector/j/)
Was die einzelnen Pakete nun machen, will ich an dieser Stelle nicht erklären, dass würde eindeutig zu weit führen. Falls alles richtig eingebunden ist, sollten ungefähr die folgenden
Libaries einebunden sein:
Als erstes Implementieren wir eine kurze Demoklasse, welche wir anschließend in die MySQL Datenbank serialisieren wollen.
Meine verwendete Klasse sieht in etwa so aus:
package de.blogd.tutorials.hibernate; /** * Beispiel Klasse an welcher die Serialisierung von * Objekten mittels Hibernate demonstriert wird. * @author Stefan König */ public class MyObject { /** * Zu serialisierender String */ private String aString; /** * Zu serialisierender Integer */ private int aNumber; /** * Zu serialisierendes String Array */ private String[] aStringArray; /** * Getter für aNumber * @return aNumber */ public int getaNumber() { return aNumber; } /** * Setter für aNumber * @param aNumber: Neu zu setzende aNumber */ public void setaNumber(int aNumber) { this.aNumber = aNumber; } /** * Getter für aString * @return aString */ public String getaString() { return aString; } /** * Setter für aString * @param aString */ public void setaString(String aString) { this.aString = aString; } /** * Getter für aStringArray * @return aStringArray */ public String[] getaStringArray() { return aStringArray; } /** * Setter für aStringArray * @param aStringArray */ public void setaStringArray(String[] aStringArray) { this.aStringArray = aStringArray; } }
Damit wäre der erste Schritt erledigt, und wir können uns um die Herstellung der Verbindung zur Datenbank kümmern. Hierzu legen wir im "root" Verzeichnis (also unter "./src/") eine xml
Datei mit dem Namen "hibernate.cfg.xml" an, in dieser wird Hibernate konfiguriert. Einzelne Erklärungen zu den verschiedenen Files befinden sich im Inhalt des xml Files.
< ?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> <session -factory> <!-- Hier werden die Zugangsdaten zur Datenbank angegeben Die Bezeichnungen sind weitestgehenden selbsterklärend --> <property name="connection.url">jdbc:mysql://localhost/HibernateSample</property> <property name="connection.username">root</property> <property name="connection.password"></property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.pool_size">1</property> <property name="current_session_context_class">thread</property> <!-- Gibt die SQL Querries auf der Konsole aus --> <property name="show_sql">true</property> <property name="format_sql">true</property> <!-- Mit dieser Option werden die Tabellen bei jeder Serialisierung neu angelegt, für das Tutorial bietet sich diese Lösung an, sollte aber beim produktiven Einsatz dann entfernt werden. --> <property name="hbm2ddl.auto">create</property> <!-- Es gibt mehrere Methoden zur Definition der zu serialisierenden Klassen, entweder direkt im hibernate.cfg.xml File, oder pro serialisierende Klasse ein eigenes File. Ich habe, zwecks der Übersicht zur Methode mit den einzelnen Files entschieden, diese werden mit den folgenden Befehl eingebunden. Die Namensgebung nach "Klassenname.hbm.xml" ist Konvention und sollte daher nicht verändert werden.--> <mapping resource="de/blogd/tutorials/hibernate/MyObject.hbm.xml" /> </session> </hibernate>
Da nun die Konfiguration für Hibernate, soweit fertig ist, können wir uns daran machen, dass Konfigurationsfile zur Serialisierung der Klasse zu erstellen. Dieses haben wir nach den
Konvention "MyObject.hbm.xml" genannt und befindet sich im selben Package bzw. Ordner wie die vorher erstellte Klasse MyObject.
< ?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> <!-- Hier geben wir an, welche Klasse wir in die Datenbank speichern möchten ("name") und wie die Tabelle mit den Objekten ("table") genannt werden soll. --> <class name="de.blogd.tutorials.hibernate.MyObject" table="MyObjects"> <!-- Hier legen wir den Primary Key fest --> <id column="id" type="java.lang.Integer"> <generator class="increment"/> </id> <!-- Hier werden die zu speichernden Attribute der Klasse bestimmt, Bei verschiedenen Attributen gibt es noch zusätzliche zur Verfügung stehende Attribute, auf diese möchte ich hier aber nicht weiter eingehen. name="": Name des Attributs (Groß/Kleinschreibung beachten!) type="": Hier wird die Klasse des Attributs angegeben. --> <property name="aString" type="java.lang.String"/> <property name="aNumber" type="java.lang.Integer"/> <!-- Es gibt auch die Möglichkeit Arrays in die Datenbank zu serialisieren, hierfür kann man sich an den folgenden Zeilen orientieren. --> <array name="aStringArray"> <key column="id" /> <list -index base="0" /> <element column="role" type="java.lang.String" /> </array> </class> </hibernate>
Nun haben wir an Konfigurationsdateien alles notwendige erstellt und können uns dem Speichervorgang in die Datenbank selbst widmen.
package hibernatetutorial; import de.blogd.tutorials.hibernate.MyObject; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; /** * In dieser Klasse wird die Serialisierung * mittels entsprechender Methoden erledigt. * @author Stefan */ public class Main { private static SessionFactory mySessionFactory; /** * Singleton zur Rückgabe einer aktuellen Session. * @return SessionFactgory */ public static SessionFactory getSessionFactory(){ if(mySessionFactory == null) mySessionFactory = new Configuration().configure().buildSessionFactory(); return mySessionFactory; } /** * Erzeugt neue Session mit Hilfe der Session Factory * @return Session */ public static Session getSession(){ return getSessionFactory().openSession(); } public static void main(String[] args){ /** * Das zu serialisierende Objekt anlegen. */ MyObject sampleObject = new MyObject(); sampleObject.setaNumber(43); sampleObject.setaString("Ich bin ein String"); String[] sampleStringArray = {"Hallo","ich","bin","ein","String","Array"}; sampleObject.setaStringArray(sampleStringArray); /** * Session zur Serialisierung anlegen. */ Session mySession = getSession(); /** * Transaktion beginnen */ Transaction myTransaction = mySession.beginTransaction(); /** * Objekte in Datenbank schreiben. */ mySession.save(sampleObject); /** * Transaktion abschließen */ myTransaction.commit(); } }
Falls dies nun fehlerfrei durchgelaufen ist, sollte der Eintrag in die Datenbank erfolgreich vorgenommen worden sein. Für das Deserialisieren der Files, werde in in den nächsten Tagen einen extra Artikel zur Verfügung stellen.
Download der Source Files (inkl. xml Files): Hibernate Tutorial Files
qT(error)
Erstmal muss ich mich wohl selbst für das absolute geniale Wortspiel in der Überschrift loben, diese Eingebung war einfach nur genial
.
Prinzipiell bin ich derzeit versucht mich in C++ mit den ersten Gehversuchen für eine GUI zu versuchen, leider wird dies auf bestmöglichem Wege durch QT verhindert. Bevor fiese Sprüche kommen, von wegen nutz doch was vernünftiges, ich hab mich "erkundigt" und mir wurde mehrfach QT empfohlen. Vielleicht auch deswegen, weil die jenigen die Empfehlung ausgesprochen haben, in ihrem Gedanken gedacht haben, der hängts nach den ersten Misserfolgen eh wieder an den Nagel
. Gestützt wurde die Entscheidung aber auch dadurch, das qt eine Java API anbietet.
Nun hab ich schon gefühlte 1000 Configure Vorgänge hinter mir, und wohl nochmal soviele Versuche ein erfolgreiches make auszuführen. Bisher bin ich kläglichst gescheitert, erste Hinweise in Foren deuten zwar darauf hin, dass es da ein Grundlegendes Problem mit Windows 7 64bit zu geben scheint, aber wirklich bestätigt oder auch wiederlegt wurde es noch nicht. Da der schwarze Peter bisher auch nicht wirklich eindeutig zugeordnet werden konnte, ob es jetzt an qt liegt oder doch an MinGW.
Aber ich bin ganz optimistisch, dass ich heute entscheidende Fortschritte machen werde.
Java vs. C++
Derzeit bin ich Intensiv am pauken von Java EE und C++, aber das Thema mit Java EE ist eine andere Geschichte gehört hier nicht hin..
Will hier nur mal meine Eindrücke wiedergeben, die sich mir als Java "Umsteiger" so ergeben haben. Besonders hierbei sticht natürlich ins Auge, die wie ich finde, deutlich besseren IDEs auf der Seite von Java, Fehler werden in Eclipse "on-the-fly" markiert, lästige Klammerungsfehler können somit quasi beim entstehen vermieden werden, in C++ muss man eben den Kompiler erst drüberlaufen lassen, in Eclipse (ist ja eigentlich nur eine Sache der IDE) wirds eben im Hintergrund gemacht.. Gut dafür kann weder Java noch CPP was, wobei ich natürlich nicht weiß, ob es entsprechende IDEs auch für C++ gibt, hab aber ehrlich gesagt auch noch nicht wirklich danach gesucht.
Der Punkt für die Übersichtlichkeit geht hingegen für mich an C++, hier die strikte Trennung zwischen Header und Implementierung find ich top, die gibts in Java in dieser direkten Form leider nicht, aber wieso sollte man
.
Referenzen: Prinzipiell bei C++ wohl etwas besser gelöst, da hier ja die Unterscheidung zwischen Pointer, Referenz und Kopie klar definiert ist, bei Java ist hier die Unterscheidung mitunter (Stichwort "call-by-reference" und "call-by-value") etwas verzwickter, aber prinzipiell auch sehr gut gelöst. Wenn man in C++ die Sache mit den Pointern einmal raus hat, ist der Unterschied zu Java minimalst, der fehlende Garbage Collector in C++ hingegen ist stellenweise find ich sehr störend, da dieser in Java einfach unheimlich viel Arbeit abnimmt und man sich über Speicher bzw. dessen Nutzung deutlich weniger Gedanken machen muss.
Die Punkt für die Dokumentation geht aber eindeutig an Java, Javadoc ist einfach "geil", dies kann in meinen Augen fast nicht besser gelöst werden. Auch wenn hier die entsprechende IDE natürlich wieder ungemein dazu beiträgt, da Eclipse die Dokumentation direkt per Mouseover anbietet.
In der Geschwindigkeit unterscheiden sich die beiden Sprachen (für mich) nicht merklich, auch wenn von Java oft behauptet wird, es sei sehr langsam. Dies kann ich bei Java nach meinen Erfahrungen nur soweit bestätigen, das die GUIs sich oft etwas träge anfühlen, aber dabei hatte ich immer öfter den Eindruck, das hängt nicht nur von Java sondern auch vom verwendeten Betriebssystem ab.
Große Unterschiede hingegeben gibt es bei der Vererbung, C++ erlaubt die Mehrfachverbung, Java hingegen nicht. Spielt aber für mich bisher keine Rolle, da ich die Mehrfachvererbung noch nie aktiv (ausser für Beispiele) genutzt habe, da man hierbei auf eine Reihe komplizierter Probleme stoßen kann. Es mag durchaus Anwendungsfälle geben, bei denen die Mehrfachvererbung einen entscheidenden Vorteil bringt, mir ist aber bisher unter realen Bedingungen keiner über den Weg gelaufen, daher ist der Vorteil für mich nur auf dem Papier existent.
Templates/Generics gibt es auch in beiden Sprachen, auch wenn deren Implementierung jeweils ein bisschen anders aussieht, beide erfüllen ihren Zweck.
Prinzpiell kann ich zusammenfassend nur sagen, beide Sprachen sind sehr gut, die Unterschiede sind teilweise sehr gering, teilweise aber auch sehr groß. Beide Sprachen sind (selbstverständlich) Turing komplett *klugscheiß*, womit sich mit ihnen die exakt selben Aufgaben lösen lassen. Mit was für einer Sprache ich in Zukunft meine Aufgaben angehen werde ist mir nach wie vor unklar, aber momentan bin ich eher daran interessiert beide gut in den Griff zu bekommen, somit wechsel ich die verwendete Sprache derzeit sehr oft ab.
JIP – Java Intensiv Program
Zurzeit hats mir Java richtig angetan, sämtliche C und Konsorten Pläne sind vorerst auf Eis gelegt, dafür pack ich mit Java richtig an, hier mal einige Literaturempfehlungen:
- Java ist auch eine Insel - mein Lieblingsnachschlagewerk
- Java & XML
- Java Kochbuch, super Werk zum nachschlagen von fertigen Code Samples, hierzu kann man aber auch diverse Internetseiten zu Rate ziehen (z.B. www.koders.com).
