Αυτός ο οδηγός θα σας δείξει τη βασική χρήση του Hibernate 3.0. Το Hibernate είναι ένα open source object relational mapping tool για Java.
Προσφαίρει υψηλής απόδοσης object/relational persistence και query service για Java.
Με το Hibernate μπορείτε να φτιάξετε persistent classes και με τη Hibernate Query Language, μπορείτε να γεφυρώσετε τις σχέσεις σε όλες τις βασεις δεδομένων. Μπορείτε να χρησημοποιήσετε native SQL ή Java-based Κριτήρια.
Αυτή τη στιγμή το Hibernate είναι το πλέον δημοφιλές object/relational mapping solution για Java
Αρχιτεκτονική του Hibernate
Το παρακάτω διάγραμμα μας δείχνει την αρχιτεκτονική του Hibernate
Όπως βλεπετε παραπάνω το Hibernate χρησημοποιεί τη βάση δεδομένων και τα αρχεια ρυθμίσεων για να υλοποιήσει persistence services (και persistent objects) στην εφαρμογή.
Για να χρησημοποιήσετε το Hibernate, πρέπει να φτιάξετε Java classes για το κάθε table στη database και μετά να κάνετε αντιστοιχίες μεταβλητών σε κολώνες.
Το Hibernate έχει τρεις βασικούς πυλώνες:
Connection Management
Ο Hibernate Connection management κάνει τη διαχείρηση των συνδέσεων με τη βάση δεδομένων. Αυτή γενικά η διαδικασία είναι η ποιο ¨ακριβή¨απο πλευράς πόρων για την εφαρμογή.
Transaction management:
Το Transaction management service χρησημοποιήται για να εκτελούνται πολλά ταυτόχρονα queries.
Object relational mapping:
Το Object relational mapping είναι μια τεχνική για τη σχεσιακή σύνδεση η οποία μετατρέπει ένα μοντ΄λο σε ένα σχεσιακό μοντέλο. Αυτό το κομμάτι στο hibernate χρησημοποιήται για να κάνει τα select, insert, update and delete απο τους πίνακες. Όταν καλούμε τη Session.save() μέθοδο σε ένα object τότε αυτό διαβαζει τις μεταβλητές και εκτελεί τα queries.
Ας κάνουμε λοιπόν ένα παράδειγμα…
Θα χρησημοποιήσω μια MySQL database για να βάλω μια γραμμή. Χρησημοποιώ το SpringSource Eclipse IDE.
Ρυθμίζουμε τα xml του Hibernate
Το Hibernate χρησημοποιεί το hibernate.cfg.xml για να φτιάξει το connection pool και να κάνει setup το environment.
[xml]
<?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>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class" >com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url" >jdbc:mysql://localhost/zenika_hibernate</property>
<property name="hibernate.connection.username">zenikaplay</property>
<property name="hibernate.connection.password">zenikapassword</property>
<property name="transaction.factory_class" >org.hibernate.transaction.JDBCTransactionFactory</property>
<!– thread is the short name for org.hibernate.context.ThreadLocalSessionContext and let Hibernate bind the session automatically to the thread –>
<property name="current_session_context_class">thread</property>
<!– this will show us all sql statements –>
<property name="hibernate.show_sql">true</property>
<mapping resource="book.hbm.xml"/>
</session-factory>
</hibernate-configuration>[/xml]
Στο παραπάνω αρχείο λέμε να χρησημοποιήσει τη βάση “zenika_hibernate” με χρήστη “zenikaplay” και κωδικό πρόσβασης “zenikapassword”
Το σημαντικότερο απο ολα επάνω είναι το tag dialect που έχει τιμή org.hibernate.dialect.MySQLDialect που λέει στο Hibernate ότι θα χρησημοποιήσει MySQL Database.
Αυτό είναι και ενα απο τα πολύ ισχυρά όπλα του Hibernate, ότι δηλαδή μπορεί να συνδεθεί σχεδόν μέ όλες τις βάσεις δεδομένων χωρίς να χρειάζεται ΚΑΜΙΑ αλλαγή στην εφαρμογή μας παρά μόνο ενα XML Tag!
Το Hibernate υποστηρίζει τις εξής διαλέκτους:
- DB2 – org.hibernate.dialect.DB2Dialect
- HypersonicSQL – org.hibernate.dialect.HSQLDialect
- Informix – org.hibernate.dialect.InformixDialect
- Ingres – org.hibernate.dialect.IngresDialect
- Interbase – org.hibernate.dialect.InterbaseDialect
- Pointbase – org.hibernate.dialect.PointbaseDialect
- PostgreSQL – org.hibernate.dialect.PostgreSQLDialect
- Mckoi SQL – org.hibernate.dialect.MckoiDialect
- Microsoft SQL Server – org.hibernate.dialect.SQLServerDialect
- MySQL – org.hibernate.dialect.MySQLDialect
- Oracle (any version) – org.hibernate.dialect.OracleDialect
- Oracle 9 – org.hibernate.dialect.Oracle9Dialect
- Progress – org.hibernate.dialect.ProgressDialect
- FrontBase – org.hibernate.dialect.FrontbaseDialect
- SAP DB – org.hibernate.dialect.SAPDBDialect
- Sybase – org.hibernate.dialect.SybaseDialect
- Sybase Anywhere – org.hibernate.dialect.SybaseAnywhereDialect
Η γραμμή είναι η γραμμή που αργότερα θα μας συνδέσει με το πίνακά μας.
Persistence Class
To Hibernate χρησημοποιεί Plain Old Java Objects (POJOs) για να κάνει map στους πίνακες της βάσης δεδομένων. Για παράδειγμα:
Ας ετοιμάσουμε ένα πίνακα στη Βάση Δεδομένων για να πειραματιστούμε
[code language=”sql”]
CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`bookname` varchar(50) NOT NULL,
`author` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `book` (`id`,`bookname`,`author`)
VALUES
(1, ‘Austin Powers: The Spy Who Shagged Me’, ‘me’), (2, ‘Dr Evil, the sad childhood’, ‘mini me’);[/code]
Φτιάχνουμε ενα POJO
[code language=”java”]
package gr.zenika.play.hibernateTutorial.pojos;
/**
*
* @author addiakogiannis
* Class to be mapped to Book Table
*/
public class Book {
private int id;
private String bookName;
private String author;
public Book(String bookName, String author){
this.bookName = bookName;
this.author = author;
}
public String getAuthor() {
return author;
}
public String getBookName() {
return bookName;
}
public int getId() {
return id;
}
public void setAuthor(String author) {
this.author = author;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public void setId(int id) {
this.id = id;
}
}
[/code]
Mapping Book Object στη Database στον πίνακα Book
Πρέπει να κατασκευάσουμε ένα XML το οποίο θα αντιστοιχεί όλα τα πεδία του πίνακα Book στο POJO Βοοκ.
Φτιάχνουμε το book.hbm.xml το οποίο και τοποθετούμε στο root package μαζί με το παραπάνω xml και γράφουμε:
[code language=”xml”]
<?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="gr.zenika.play.hibernateTutorial.pojos.Book" table="book">
<id name="id" column="id" >
<generator class="increment"/>
</id>
<!– Be carefull its case sensitive –>
<property name="bookName" column="bookname" />
<property name="author" column="author" />
</class>
</hibernate-mapping>
[/code]
Και τωρα φτιάχνουμε τη main class για να δοκιμάσουμε!
[code language=”java”]
package gr.zenika.play.hibernateTutorial;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author addiakogiannis
*
*/
public class FirstExample {
final static Logger logger = LoggerFactory.getLogger(FirstExample.class);
public static void main(String[] args) {
Session session = null;
try {
// This step will read hibernate.cfg.xml and prepare hibernate for use
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.openSession();
//Create Select Clause HQL
String SQL_QUERY = "Select id,bookName,author from Book";
Query query = session.createQuery(SQL_QUERY);
List<Object[]> results = query.list();
for(Object[] b : results){
//Each row returns an Object[]. Each field on the query is mapped on that
//so Object[0] -> BookID Author -> Object[2] (not 1) etc
System.out.println("========================");
System.out.println("BookID -> "+b[0]);
System.out.println("Author -> "+b[2]);
System.out.println("BookName -> "+b[1]);
System.out.println("========================");
}
System.out.println("Done");
} catch (Exception e) {
e.printStackTrace();
} finally {
session.flush();
session.close();
}
}
}
[/code]
Αν ολα πανε καλα θα πρέπει να δούμε στο output του terminal
Hibernate: select book0_.id as col_0_0_, book0_.bookname as col_1_0_, book0_.author as col_2_0_ from book book0_
========================
BookID -> 1
Author -> me
BookName -> book1
========================
========================
BookID -> 2
Author -> mini me
BookName -> book2
========================
Done
Αν θέλαμε να εισάγουμε γραμμή
[code language=”java”]
package gr.zenika.play.hibernateTutorial;
import gr.zenika.play.hibernateTutorial.pojos.Book;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author addiakogiannis
*
*/
public class SeccondExample {
final static Logger logger = LoggerFactory.getLogger(SeccondExample.class);
public static void main(String[] args) {
Session session = null;
try {
// This step will read hibernate.cfg.xml and prepare hibernate for use
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.openSession();
logger.info("Inserting reccord");
Book book = new Book("In Bed with miniMe","WannaHumbAlot");
session.save(book);
logger.info("Done");
} catch (Exception e) {
e.printStackTrace();
} finally {
// Actual book insertion will happen at this step
session.flush();
session.close();
}
}
}
[/code]
Αν όλα πανε καλά θα δούμε
INFO: Inserting reccord
Hibernate: select max(id) from book
Jun 4, 2010 1:21:57 AM gr.zenika.play.hibernateTutorial.SeccondExample main
INFO: Done
Hibernate: insert into book (bookname, author, id) values (?, ?, ?)
BUILD SUCCESSFUL
Για delete εγγραφης
[code language=”java”]
public class ThirdExample {
final static Logger logger = LoggerFactory.getLogger(ThirdExample.class);
public static void main(String[] args) {
Session session = null;
try {
// This step will read hibernate.cfg.xml and prepare hibernate for use
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.openSession();
logger.info("Deleting reccord");
Book book = new Book();
book.setId(4); //id of row for deletion
session.delete(book);
logger.info("Done");
} catch (Exception e) {
e.printStackTrace();
} finally {
// Actual book insertion will happen at this step
session.flush();
session.close();
}
}
}
[/code]
Αν όλα πανε καλά θα δούμε
INFO: Deleting reccord
Jun 4, 2010 1:31:04 AM gr.zenika.play.hibernateTutorial.ThirdExample main
INFO: Done
Hibernate: delete from book where id=?
BUILD SUCCESSFUL
Και τέλος για update εγγραφής
[code language=”java”]
package gr.zenika.play.hibernateTutorial;
import gr.zenika.play.hibernateTutorial.*;
import gr.zenika.play.hibernateTutorial.pojos.Book;
import gr.zenika.play.hibernateTutorial.pojos.Book;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author addiakogiannis
*
*/
public class FourthExample {
final static Logger logger = LoggerFactory.getLogger(FourthExample.class);
public static void main(String[] args) {
Session session = null;
try {
// This step will read hibernate.cfg.xml and prepare hibernate for use
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
session = sessionFactory.openSession();
logger.info("updating reccord");
Book book = new Book();
book.setId(2);
book.setBookName("In Bed with miniMe and me!");
book.setAuthor("WannaHumbAlot");
session.update(book);
logger.info("Done");
} catch (Exception e) {
e.printStackTrace();
} finally {
// Actual book insertion will happen at this step
session.flush();
session.close();
}
}
}
[/code]
Με αποτέλεσμα…
INFO: Done
Hibernate: update book set bookname=?, author=? where id=?
BUILD SUCCESSFUL
περιμένω τα σχόλια σας…
Αν την ιδια διαδικασια θελαμε να την κανουμε σε browser?
Τι εννοεις?