Εισαγωγη στο Hibernate

Αυτός ο οδηγός θα σας δείξει τη βασική χρήση του 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 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>

Στο παραπάνω αρχείο λέμε να χρησημοποιήσει τη βάση “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 στους πίνακες της βάσης δεδομένων. Για παράδειγμα:

Ας ετοιμάσουμε ένα πίνακα στη Βάση Δεδομένων για να πειραματιστούμε

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');

Φτιάχνουμε ενα POJO

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;
}
}

Mapping Book Object στη Database στον πίνακα Book

Πρέπει να κατασκευάσουμε ένα XML το οποίο θα αντιστοιχεί όλα τα πεδία του πίνακα Book στο POJO Βοοκ.

Φτιάχνουμε το book.hbm.xml το οποίο και τοποθετούμε στο root package μαζί με το παραπάνω 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>

Και τωρα φτιάχνουμε τη main class για να δοκιμάσουμε!

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();
}
}
}

Αν ολα πανε καλα θα πρέπει να δούμε στο 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
Αν θέλαμε να εισάγουμε γραμμή

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();
}
}
}

Αν όλα πανε καλά θα δούμε

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 εγγραφης

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();
}
}
}

Αν όλα πανε καλά θα δούμε

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 εγγραφής

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();
}
}
}

Με αποτέλεσμα…

INFO: Done

 

Hibernate: update book set bookname=?, author=? where id=?

BUILD SUCCESSFUL
περιμένω τα σχόλια σας…

Facebook Comments

2 thoughts on “Εισαγωγη στο Hibernate

  1. Pavlos Reply

    Αν την ιδια διαδικασια θελαμε να την κανουμε σε browser?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.