Sunday 12 December 2010

JavaEE : Hibernate tutorial


Hibernate is an object-relational mapping (ORM) library for the Java language, providing a framework for mapping an object-oriented domain model to a traditional relational database.

Why it's need?
For example you want insert something in your database.

In sql:
PreparedStatement prep = con
.prepareStatement("insert into weights values(?,?,?,?,?,?,?);");
prep.setString(2, "vasea");
prep.setString(3, "21");
prep.setString(4, "male");
prep.setString(5, "77");
prep.setString(6, "185");
prep.setString(7, "76");
prep.execute();
In hibernate:  
Factory.getInstance().getEmployeDAO().addEmployee(new Human("vasea",21,77,185,76));  
Hibernate gives you possibility to manage database abstractly, also it's useful when you want to change some logic.

Hibernate Setup
To use Hibernate with Eclipse you should download Hibernate libraries (hibernate-annotations-3.4.0.GA + hibernate-distribution-3.3.2.GA-dist) and export them to the project. (Download from official site or finished my library jars)
You may create your library, that contains required files:
  • click in Eclipse Window > Preferences > Java > Build Path > User Libraries  and click New.
  • enter name, and click Add jars..
  •  after library creation, you should include it click Project > Properties > Java Build Path > Add library > User library
SQL Setup
You should create database, any what do you want. I use db-derby . You should configure hibernate, for working with your database. For this you need database-url, password and user name. You can create database from Eclipse in Data Source Explorer.

Database diagramm:

hiberante.cfg.xml 
This file using to describe configuration of your database. When you work with annotations use <mapping class="entity.Human"/> otherwise use <mapping resource="entity/Human.hbm.xml"/>.Next i will use approach with annotations.

hiberante.cfg.xml  sample:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

  <hibernate-configuration>
   <session-factory>
    <!-- Database connection settings -->
    <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
    <property name="connection.url">jdbc:derby://localhost:1527/HibernateDb;create=true</property>
    <property name="connection.username">user</property>
    <property name="connection.password">password</property>

    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">2</property>

    <!-- SQL dialect -->
    <property name="dialect">org.hibernate.dialect.DerbyDialect</property>

    <property name="current_session_context_class">thread</property>

    <!-- Disable the second-level cache  -->
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

    <!-- Echo all executed SQL to stdout -->
    <property name="show_sql">true</property>

    <mapping class="entity.Employer"/>
    <mapping class="entity.Human"/>
   </session-factory
</hibernate-configuration> 


HibernateUtil class:
Hibernate use this class  for getting data from hiberante.cfg.xml and configure hibernate

public class HibernateUtil {
   private static final SessionFactory sessionFactory;
     static {
       try {  
         sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
       } catch (Throwable ex) {
         System.err.println("Initial SessionFactory creation failed." + ex);
         throw new ExceptionInInitializerError(ex);
       }
     }

     public static SessionFactory getSessionFactory() {
       return sessionFactory;
     }
 }
 

Entities
You should create simple pojo classes thats will store structure of our tables(id, name, sex and etc.)
Also you should specify how tables are related.

Entities sample:
@Entity
@Table(name="EMPLOYEE")
public class Employee {
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(name="employee_id")
 private int employeeId;
 
 @Column(name="salary")
 private double salary;
 
 @OneToOne(cascade = CascadeType.ALL,fetch=FetchType.LAZY)
 @PrimaryKeyJoinColumn
 private Human humData;
 
 public int getEmployeeId() {
  return employeeId;
 }
 public void setEmployeeId(int employeeId) {
  this.employeeId = employeeId;
 }
 public int getSalary() {
  return salary;
 }
 public void setSalary(int salary) {
  this.salary = salary;
 }
 public int getHumData() {
  return humData;
 }
 public void setHumData(int humData) {
  this.humData = humData;
 } 
}

@Entity
@Table(name="HUMAN")
public class Human {
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(name="human_id")
 private int humId;
 
 @Column(name="hum_name")
 private String name; 
 
 public int getHumId() {
  return humId;
 }
 public void setHumId(int humId) {
  this.humId = humId;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
}

DAO:
It's just simple interface with methods to interact with your table. Here is description. You should create interface for every table, but if all methods are the same you can use this way.

DAO sample: 
public interface HumanDAO {
 void addHuman(Human human) throws SQLException;
 void updateHuman(Human hum) throws SQLException;
 public Collection getAllHumans() throws SQLException;
 public Human getHumanById(int id) throws SQLException;
 public void deleteHuman(Human hum) throws SQLException;
}
DAOImpl: 
public class HumanDAOImpl implements HumanDAO {

 @Override
 public Human getHumanById(int id) throws SQLException {
  Session session = null;
  Human human = null;
  try {
   session = HibernateUtil.getSessionFactory().openSession();
   human = (Human) session.load(Human.class, id);
   Hibernate.initialize(human);
  } catch (Exception e) {
   System.out.print("Error in getting by id");
  } finally {
   if (session != null && session.isOpen()) {
    session.close();
   }
  }
  return human;
 }

 @Override
 public void addHuman(Human human) throws SQLException {
   Session session = null;
      try {
        session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        session.save(human);
        session.flush();
        session.getTransaction().commit();
      } catch (Exception e) {
       System.out.println("Error in inserting: " + e.toString());
      } finally {
        if (session != null && session.isOpen()) {

          session.close();
        }
      }  
  
 }
  //etc.))
}
Factory: 
This class need to return your dao. Also you can read here

public class Factory {
 
  private static EmployeeDAO employeeDAO = null;
  private static HumanDAO humanDAO = null;
  
  public static synchronized Factory getInstance(){
      if (instance == null){
        instance = new Factory();
      }
      return instance;
    }

  public EmployeeDAO getEmployee(){
   if (employeeDAO == null){
    employeeDAO = new EmployeeDAOImpl();
      }
      return employeeDAO;
  }
  public HumanDAO getHumanDAO(){
   if (humanDAO == null){
    humanDAO = new HumanDAOImpl();
      }
      return humanDAO;
  }

Main method:
Finally we running our project, for this we should create our tables(with hibernate or manually).Next we adding data to our tables. We call Factory thats return required entity and use our methods.

public class Main {
 public  static void createTables(){
  AnnotationConfiguration config = new AnnotationConfiguration();
  config.addAnnotatedClass(Human.class);
  config.addAnnotatedClass(Employee.class);
  config.configure("hibernate.cfg.xml");  
  new SchemaExport(config).create(true,true);
 }
        public static void main(String[] args) {
        //creating tables
          createTables();
          Human hum = new Human();
          hum.setName("Vasea");
          Employee emp = new Employee();
          emp.setSalary(1000);
          emp.setHumData(hum);
         //adding data 
   try {
         Factory.getInstance().getEmployeDAO().addEmployee(emp);  
  } catch (SQLException e) {
   e.printStackTrace();
  }
       }
}

References 
Very useful are Official docs abouth annotations.
Video lesson on YouTube about hibernate here.
Hibernate basics (Russian lang) here

Ps: This is not optimal solution, everything becomes really easy when you use Application server(Jboss, Glasfish and etc.) with some framework

2 comments:

  1. You have a lot of boilerplate code. Use Spring in order to minimize it. Or in case you are constrained or you don't have the possibility to use it, create at least a GenericDao that will provide the common CRUD operations for your entities.

    ReplyDelete