Hibernate Framework

Το Hibernate Framework είναι λογισμικό ανοιχτού κώδικα (ελεύθερο λογισμικό) που σκοπό έχει να συνδέσει τα αντικείμενα που δημιουργούνται σε μια αντικειμενοστρεφή γλώσσα προγραμματισμού (Java) με τους πίνακες μιας σχεσιακής βάσης δεδομένων. Η σύνδεση αυτή επιτυγχάνεται με την χρήση επιπρόσθετης πληροφορίας (metadata) που τοποθετείται κατάλληλα (μαζί με τον κώδικα Java ή σε ξεχωριστά xml αρχεία) και περιγράφει την αντιστοιχία μεταξύ των αντικειμένων και της βάσης δεδομένων. Γενικά το Hibernate προσφέρει την αυτόματη μετατροπή της μιας μορφής (αντικείμενα) στην άλλη (σχεσιακή βάση δεδομένων).

Ιστορικό 

Το Hibernate είναι λογισμικό που αρχικά κατασκευάστηκε από προγραμματιστές ανά τον κόσμο με συντονιστή τον Gavin King. Αργότερα η εταιρεία JBoss inc. προσέλαβε τους κύριους προγραμματιστές και ανέπτυξε περαιτέρω το Hibernate σχετικά με τα στάνταρτ της πλατφόρμας J2EE. Σήμερα η τελευταία έκδοση του Hibernate είναι η 3.x και ενσωματώνει χαρακτηριστικά όπως interceptor/callback architecture, user defined filters και τα Annotations που παρουσιάστηκαν στη Java (JDK 5.0+).

Χρήση 

Το Hibernate συγκαταλέγεται στην κατηγορία του λογισμικού ORM (object/relational mapping). Το λογισμικό ORM στοχεύει στη δημιουργία μιας διεπαφής (interface) μεταξύ των διαδεδομένων σχεσιακών βάσεων δεδομένων και του αντικειμενοστρεφούς προγραμματισμού. Με απλά λόγια, προσφέρει τη χρησιμοποίηση μιας σχεσιακής βάσης δεδομένων ως να ήταν αντικειμενοστρεφής. Για να το επιτύχει αυτό δημιουργεί αντιστοιχίες μεταξύ των εννοιών του αντικειμενοστρεφούς προγραμματισμού (συσχετίσεις, κληρονομικότητα, πολυμορφισμός) - που δεν υπάρχουν σε μια σχεσιακή βάση δεδομένων - και των πινάκων και σχέσεων μεταξύ των πινάκων μιας σχεσιακής βάσης. Με αυτό τον τρόπο ο προγραμματιστής βλέπει τελικά μια αντικειμενοστρεφή βάση δεδομένων, παρ´όλο που στην ουσία χρησιμοποιεί μια σχεσιακή. Έτσι ο προγραμματιστής χρησιμοποιεί τα αντικείμενα της συγκεκριμένης εφαρμογής, τα τροποποιεί σχετικά με τη λογική της εφαρμογής που αναπτύσσει και τα αποθηκεύει (τροποποιεί, διαγράφει και αναζητά) στη βάση ως αντικείμενα, σκεπτόμενος δηλαδή με αντικειμενοστρεφείς έννοιες και όχι με βάση το σχήμα της σχεσιακής βάσης δεδομένων. Σε αυτό το σημείο είναι το Hibernate που, γνωρίζοντας την αντιστοιχία μεταξύ βάσης και λογικής της εφαρμογής, αναλαμβάνει να κατασκευάσει την κατάλληλη εντολή της SQL, η οποία και στέλνεται τελικά στη βάση δεδομένων. Έπειτα, τα αποτελέσματα που επιστρέφει η βάση, το Hibernate τα επιστρέφει στον προγραμματιστή ως αντικείμενα της εφαρμογής. Είναι δηλαδή ένα ενδιάμεσο επίπεδο μεταξύ της εφαρμογής και της βάσης δεδομένων.

Χαρακτηριστικά/Πλεονεκτήματα 

Το Hibernate προσφέρει τα παρακάτω στον προγραμματιστή:

 Παραγωγικότητα: Στην ανάπτυξη λογισμικού ένα μεγάλο μέρος της προγραμματιστικής προσπάθειας αφιερώνεται στη διεπαφή της εφαρμογής με τη βάση δεδομένων. Το Hibernate αυτοματοποιώντας τις βασικές λειτουργίες Δημιουργία/Ανάγνωση/Τροποποίηση/Διαγραφή (CRUD – Create Read Update Delete) επιτρέπει αρχικά στον προγραμματιστή να επικεντρώνει την προσπάθειά του στη λογική της εφαρμογής (business logic). Επίσης, υπάρχει η δυνατότητα να ακολουθηθούν δύο στρατηγικές ανάπτυξης λογισμικού: είτε αρχίζοντας από το μοντέλο δεδομένων είτε από τη βάση δεδομένων. Αυτό μειώνει σε μεγάλο βαθμό το χρόνο ανάπτυξης.

 Συντηρησιμότητα: Με τη χρήση του Hibernate γράφονται σημαντικά λιγότερες γραμμές κώδικα και ο κώδικας είναι πιο κατανοητός και καλογραμμένος. Αυτό κάνει την συντήρηση της εφαρμογής ευκολότερη.

 Ανεξαρτησία από τη βάση δεδομένων: Με τη συμβατότητα του Hibernate με διαφορετικές βάσεις δεδομένων και τη δυνατότητα σύνδεσής του με τη βάση μέσω δηλώσεων οριζομένων σε ειδικό αρχείο η αναπτυσσόμενη εφαρμογή μπορεί με ελάχιστες τροποποιήσεις να χρησιμοποιηθεί με βάσεις δεδομένων διαφορετικών κατασκευαστών. Το γεγονός αυτό στερεί μεν από το Hibernate την εκμετάλλευση των ιδιαίτερων χαρακτηριστικών της χρησιμοποιούμενης βάσης, όμως, και σε αυτή την περίπτωση, δίνεται η δυνατότητα χρήσης πηγαίας SQL μέσα στο Hibernate που εκμεταλλεύεται τα ιδιαίτερα αυτά χαρακτηριστικά. Αυτό βέβαια μειώνει την ανεξαρτησία του Hibernate.

Παράδειγμα 

Το παράδειγμα που αναφέρεται σε αυτή την παράγραφο είναι πολύ βασικό και παρουσιάζει μια πολύ απλή χρήση του Hibernate. Για λεπτομερέστερη περιγραφή των δυνατοτήτων του Hibernate επισκευθείτε την επίσημη ιστοσελίδα.

Για το παράδειγμά μας, υποθέτουμε πως έχουμε ένα μοντέλο στο οποίο ένας άνθρωπος (Person) μπορεί να διαθέτει κανένα ή περισσότερα οχήματα (Vehicle). Το αντίστοιχο διάγραμμα που δείχνει τα αντικείμενα του μοντέλου μας είναι το παρακάτω:

Η κατάσταση αυτή μπορεί να μεταφραστεί σε σχεσιακή βάση δεδομένων χρησιμοποιώντας δύο πίνακες (PERSON και VEHICLE) με τα αντίστοιχα πεδία όπως φαίνεται παρακάτω:

Το πεδίο PERSON_ID του πίνακα VEHICLE είναι εξωτερικό κλειδί (foreign key) και συνδέει το PERSON με τα VEHICLEs τα οποία κατέχει. Στην εφαρμογή μας πρέπει να κατασκευάσουμε δύο αντικείμενα τα Person και Vehicle:

Αρχείο Person.java

 package example;
 class Person{
     private long id;
     private String name;
     private boolean sex;
     private int age;
     private List vehicles;
     public Person(){}
     public String getName(){
         return this.name;
     }
     public void setName(String name){
         this.name=name;
     }
     //το ίδιο και για τα άλλα τέσσερα χαρακτηριστικά
      …
 }

Αρχείο Vehicle.java

 package example;
 class Vechicle{
     private long id;
     private String registration; //πινακίδα
     private int engine; //κυβισμός
     private String make; //μάρκα 
     public Vehicle(){}
     public String getRegistration(){
         return this.registration;
     }
     public void setRegistration(String registration){
         this.registration=registration;
     }
     //το ίδιο και για τα άλλα τρία χαρακτηριστικά
      …
 }

Χρησιμοποιώντας το Hibernate πρέπει να κατασκευάσουμε τα XML αρχεία που περιγράφουν την αντιστοιχία μεταξύ των αντικειμένων και των πινάκων της βάσης δεδομένων:

Αρχείο engine/Person.hbm.xml
 <xml version = “1.0”?>
 <!DOCTYPE hibernate-mapping PUBLIC “-//Hibernate/Hibernate Mapping DTD//EN”
 “http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd”>
     <class name=”example.Person” table=”PERSON”>
         <id name=”id” column=”PERSON_ID” type=”long”>
             <generator class=”native”>
         </id>
         <property name=”name” column=”P_NAME” type=”string”/>
         <property name=”sex” column=”P_SEX” type=”boolean”/>
         <property name=”age” column=”P_AGE” type=”integer”/>
         <set name=”vehicles” inverse=”true” cascade=”save-update”>
             <key column=”PERSON_ID” />
             <one-to-many class=”example.Vehicle”/>
         </set>
    </class>		
 </hibernate-mapping>

Αρχείο engine/Vehicle.hbm.xml

 <xml version = “1.0”?>
 <!DOCTYPE hibernate-mapping PUBLIC “-//Hibernate/Hibernate Mapping DTD//EN”
 “http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd”>
     <class name=”example.Vehicle” table=”VEHICLE”>
         <id name=”id” column=”VEHICLE_ID” type=”long”>
             <generator class=”native”>
         </id>
         <property name=”registration” column=”V_REGISTRATION” type=”string”/>
         <property name=”engine” column=”V_ENGINE” type=”integer”/>
         <property name=”make” column=”V_MAKE” type=”string”/>
         <many-to one name=”person” column=”PERSON_ID” class=”example.Person” not-null=”true”/>
     </class>		
 </hibernate-mapping>

Επίσης πρέπει να ορίσουμε ένα αρχείο με τα χαρακτηριστικά της βάσης δεδομένων που χρησιμοποιούμε. Για παράδειγμα, αν χρησιμοποιούμε PostgreSQL και η βάση μας λέγεται myBD τότε το αρχείο μας περιέχει τα παρακάτω:

Αρχείο hibernate.properties

 hibernate.connection.driver_class= org.postgresql.Driver
 hibernate.connection.url=jdbc:postgresql://localhost/myDB
 hibernate.connection.username = user
 hibernate.connection.password = pass
 hibernate.dialect = net.sf.hibernate.dialect.PostgreSQLDialect

Γράφοντας τα παραπάνω έχουμε κάνει τα εξής:

 Έχουμε αντιστοιχίσει τα αντικείμενα Person και Vehicle με τους πίνακες PERSON και VEHICLE της βάσης δεδομένων (με το class των XML αρχείων).

 Έχουμε ορίσει τα πρωτεύοντα κλειδιά (με το id των XML αρχείων).

 Έχουμε αντιστοιχίσει τα χαρακτηριστικά των αντικειμένων (name, sex, age, registration, engine, make) με τις αντίστοιχες στήλες των σχεσιακών πινάκων (P_NAME, P_SEX, P_AGE, V_REGISTRATION, V_ENGINE, V_MAKE) (με το property των XML αρχείων).

 Έχουμε ορίσει τη συσχέτιση (association) μεταξύ των δύο πινάκων (με τα many-to-one, one-to-many και set των XML αρχείων).

 Έχουμε ορίσει τη βάση δεδομένων που θα χρησιμοποιήσει το Hibernate (το αρχείο αυτό τοποθετείται στο classpath της εφαρμογής μας και to Hibernate το βρίσκει αυτόματα).

Έχοντας ορίσει όλα αυτά μπορούμε να αρχίσουμε το Hibernate και να αναφερθούμε στα αντικείμενά μας όπως περιγράφεται στη συνέχεια:

 //αρχίζουμε το Hibernate
 Configuration cfg=new Configuration();
 cfg.addResource(“engine/Person.hbm.xml”);
 cfg.addResource(“engine/Vehicle.hbm.xml”);
 SessionFactory session=new cfg.buildSessionFactory();

 //δουλεύουμε με τα αντικείμενα
 //αποθήκευση αντικειμένων
 Session session=getSessionFactory().openSession();
 Transaction tx=session.beginTransaction();
 Vehicle v=new Vehicle();
 v.setRegistration(“XXX-1234”);
 v.setEngine(2000);
 v.setMake(“Nissan”);
 Person p=new Person();
 p.setName(”Nick”);
 p.setSex(true); //άνδρας
 p.setAge(29);
 p.getVehicles().add(v);
 session.save(p);
 tx.commit();
 session.close();

 //αναζήτηση αντικειμένων
 Session newSession=getSessionFactory().openSession();
 Transaction newTx=newSession.beginTransaction();
 Person p2 = (Person) newSession.load(Person.class, new Long(1));
 List vehicles=p2.getVehicles();
 System.out.println(“Number of Vehicles: ”+vehicles.size());
 newTx.commit();
 newSession.close();

Στο παράδειγμα αυτό αποθηκεύτηκαν στη βάση δεδομένων, στους αντίστοιχους πίνακες, τα αντικείμενά p και v και αναζητήθηκαν το person και τα vehicles που έχει. Παρατηρήστε ότι σε όλη την έκταση του παραδείγματος δε χρησιμοποιήσαμε καθόλου SQL κώδικα, πράγμα που επιτρέπει το διαχωρισμό του business logic της εφαρμογής από τη βάση δεδομένων. Ο προγραμματιστής μπορεί ετσι να αφοσιωθεί στην κωδικοποίηση της εφαρμογής χωρίς να συνδέει στενά τον κώδικα της εφαρμογής με τον κώδικα που χρειάζεται για την τροποποίηση των δεδομένων στη βάση. Επίσης, οι αλλαγές στη βάση δεδομένων είναι ευκολότερο να αντιμετωπιστούν στα XML αρχεία των αντιστοιχίσεων παρα οπουδήποτε μέσα στον κώδικα. Ακόμα, χρειάζονται πολύ λιγότερες γραμμές κώδικα για τις βασικές τροποποιήσεις των δεδομένων (CRUD – Create Read Update Delete) στη βάση δεδομένων. Αυτά, σε μεγάλης έκτασης εφαρμογές, αποδυκνύονται πολύτιμα, τόσο όσον αφορά τον χρόνο ανάπτυξης της εφαρμογής όσο και στην αποσφαλμάτωση του κώδικα κατα την ανάπτυξη της εφαρμογής.

Το παράδειγμα που περιγράψαμε είναι πολύ απλό και ενδεικτικό της χρήσης του Hibernate. Το Hibernate υποστηρίζει πολύπλοκες συσχετίσεις μεταξύ αντικειμένων όπως συσχετίσεις (associations), πολυμορφισμό (polymorphism) και κληρονομικότητα (inheritance) και τις κυριότερες βάσεις δεδομένων (Oracle, MySQL, PostgreSQL, Microsoft SQL Server, DB2, Sybase κτλ.). Επίσης μπορεί να χρησιμοποιηθεί τόσο σε unmanaged (π.χ. το παράδειγμα που αναφέραμε) όσο και σε managed application περιβάλλοντα (π.χ. JBoss).

Δείτε επίσης 

 EJB 3.0
 NHibernate
 Spring Framework
 Serialization
 iBATIS
 JDO

Εξωτερικοί σύνδεσμοι 
 http://www.hibernate.org/ To Hibernate.org είναι ο επίσημος ιστοχώρος για την τεχνολογία Hibernate. Μπορείτε να το κατεβάσετε από εκεί, καθώς επίσης να διαβάσετε ενδιαφέροντα κείμενα που περγράφουν τη λειτουργία και τη χρήση του.

Βιβλιογραφία 
 

Java
Ελεύθερο λογισμικό