Hibernate Basics

Sang Shin, sang.shin@sun.com, Sun Microsystems, www.javapassion.com/j2ee


This hands-on lab takes you through the basics of building Hibernate application. The topics that will be covered in this lab include transactional behavior, basic DAO (Data Access Object) pattern, etc.  It is expected that you have done Hibernate Step By Step hands-on lab. In this lab, you are going to open and run various NetBeans projects that are provided as part of the hands-on lab zip file and then study the code.


Expected duration: 150 minutes

Software Needed

Before you begin, you need to install the following software on your computer. The Hibernate library files  are already included as part of the hands-on lab zip file so you don't have to download Hibernate yourself.


Change Log



Lab Exercises


Exercise 0: Start Java DB (code-named as Derby) database server and create "mydatabase" database

    1. Start the Java DB (Derby) database server if you have not done so yet. 
    2. Create "mydatabase" database if you have not done so yet. 
3. Install HIbernate plug-in to the NetBeans IDE, as described here.

Exercise 1: Perform persistence operations in a transaction

    In this exercise, you are going to exercise transactional demarcation operations such as creating transactional context object, committing, and performing rollback.

    1. Open and run "HibernateTransactionWithoutRollback" project
    2. Look under the hood of the "HibernateTransactionWithoutRollback" project
    3. Open and run "HibernateTransactionWithRollback" project
    4. Look under the hood of the "HibernateTransactionWithRollback" project

(1.1) Open and run "HibernateTransactionWithoutRollback" project


1. Open HibernateTransactionWithoutRollback NetBeans project. 

2. Build and run HibernateTransactionWithoutRollback project.

Name of product retrieved from database = ProductNameOld1
Begin transaction...
Changing name of product to ProductNameNew by product.setName() method

About to do Commit...
Name of product before Commit = ProductNameNew
After Commit...
Name of product after Commit = ProductNameNew

Changing name of product to ProductNameSangShin by product.setName() method
Name of product before Refresh = ProductNameSangShin

About to Refresh...
Name of product after Refresh = ProductNameNew
Name of product after Commit = ProductNameNew

******** Table: Product *******
+-------------+--------------------------------+--------------------------------+------------------------+-------------+
|      ID        |              NAME                  |           DESCRIPTION         |          PRICE           |  SUPPLIERID
+-------------+--------------------------------+--------------------------------+------------------------+-------------+
| 1              | ProductNameNew             | Description for Product 1 | 2.0                         | 1              |
| 2              | ProductNameOld2            | Description for Product 2  | 22.0                       | 1              |
| 3              | ProductNameOld3            | Description for Product 3  | 30.0                       | 2              |
+-------------+--------------------------------+--------------------------------+------------------------+-------------+
Figure-1.11: Result


Trouble-shooting: If you see the following error condition in the Output window, it is highly likely due to the fact the database server is not running.
Solution: Start the database server as described in Exercise 0 above.

15   [main] WARN  org.hibernate.cfg.SettingsFactory  - Could not obtain connection metadata
org.apache.derby.client.am.DisconnectException: java.security.PrivilegedActionException : Error opening socket to server localhost on port 1527 with message : null
        at org.apache.derby.client.net.NetAgent.<init>(Unknown Source)
        at org.apache.derby.client.net.NetConnection.newAgent_(Unknown Source)
        at org.apache.derby.client.am.Connection.<init>(Unknown Source)
        at org.apache.derby.client.net.NetConnection.<init>(Unknown Source)
        at org.apache.derby.jdbc.ClientDriver.connect(Unknown Source)
        at java.sql.DriverManager.getConnection(DriverManager.java:582)
        at java.sql.DriverManager.getConnection(DriverManager.java:154)
        at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:110)
        at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:76)
        at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:1933)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1216)
        at HibernateUtil.<clinit>(HibernateUtil.java:26)
        at Main.main(Main.java:9)
Got an exception!
Figure-1.12: Error condition when database server is not running

                                                                                                                return to top of the exercise


(1.2) Look under the hood of the "HibernateTransactionWithoutRollback" project


1. Study the Main.java.  Pay special attention to the bold-fonted parts.

import java.util.*;

import java.sql.*;
import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.criterion.*;

public class Main {
   
    public static void main(String[] args) {
       
        // Set up database tables and test data
        HibernateUtil.droptable("drop table Product");
        HibernateUtil.setup("create table Product ( id int, name VARCHAR(30), description VARCHAR(30), price double,supplierId int)");
        prepareTestData();
       
        // Perform the read operation
        SessionFactory factory = new Configuration().configure().buildSessionFactory();
        Session session = factory.openSession();
       
        // Perform a read operation just to verify the product name in the database
        Product product = null;
        product = (Product)session.createQuery("from Product where name='ProductNameOld1'").uniqueResult();
        System.out.println("Name of product retrieved from database = " + product.getName());
       
        // Begin transaction and do a commit
        System.out.println("Begin transaction...");
        Transaction tx = session.beginTransaction();
        System.out.println("Changing name of product to ProductNameNew by product.setName() method");
        product.setName("ProductNameNew");
        System.out.println("\nAbout to do Commit...");
        System.out.println("Name of product before Commit = " + product.getName());
        tx.commit();
        System.out.println("After Commit...");
        System.out.println("Name of product after Commit = " + product.getName());
       
        // Begin transaction and do Refresh
        tx = session.beginTransaction();
        System.out.println("\nChanging name of product to ProductNameSangShin by product.setName() method");
        product.setName("ProductNameSangShin");
        System.out.println("Name of product before Refresh = " + product.getName());
       
        // The object will be refreshed with the data from the database
        // Note that product name ProductNameSangShin in the product object will be
        // replaced by the ProductNameNew from the database.
        System.out.println("\nAbout to Refresh...");
        session.refresh(product);
        System.out.println("Name of product after Refresh = " + product.getName());
        tx.commit();
        System.out.println("Name of product after Commit = " + product.getName());
       
        // Display tables
        HibernateUtil.checkData("select * from Product");
       
    }
   
    // Below are utility methods
   
    private static void prepareTestData(){
        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();
       
        Product product1 = new Product("ProductNameOld1","Description for Product 1", 2.0);
        session.save(product1);
       
        Product product12 = new Product("ProductNameOld2","Description for Product 2", 22.0);
        session.save(product12);
       
        Product product2 = new Product("ProductNameOld3", "Description for Product 3", 30.0);
        session.save(product2);
       
        tx.commit();
        HibernateUtil.closeSession();
    }
   
}
Code-1.21:Main.java

2. Study Product.java as shown in Code-1.22 below.  Note that the Product class is a POJO class.

public class Product {
    private int id;
   
    private String name;
    private String description;
    private double price;
   
    public Product() {
        super();
    }
   
    public Product(String name, String description, double price) {
        super();
        this.name = name;
        this.description = description;
        this.price = price;
    }
   
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
   
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
}
Code-1.22: Product.java

3. Study Product.hbm.xml.  This is the mapping file for the Product class.
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="Product">
        <id name="id" type="int">
            <generator class="increment"/>
        </id>
       
        <property name="name" type="string"/>
        <property name="description" type="string"/>
        <property name="price" type="double"/> 
    </class>
</hibernate-mapping>
Code-1.23: Product.hbm.xml

4. Study hibernate.cfg.xml.  This is hibernate configuration file. 

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/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/mydatabase</property>
        <property name="connection.username">app</property>
        <property name="connection.password">app</property>
       
        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>
       
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.DerbyDialect</property>
       
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">false</property>
       
        <!-- Mapping files -->
        <mapping resource="Product.hbm.xml"/>
    </session-factory>
</hibernate-configuration>
Code-1.23: hibernate.cfg.xml

                                                                                                              return to top of the exercise

(1.3) Open and run "HibernateTransactionWithRollback" project


In this step, you are going to exercise "rollback" operation.

1. Open HibernateTransactionWithRollback NetBeans project. 

2. Build and run HibernateTransactionWithRollback project.

Name of product retrieved from database = ProductNameOld1
Begin transaction...
Changing name of product to ProductNameNew...

About to do Rollback...
Name of product before rollback = ProductNameNew
After Rollback...
Name of product after rollback = ProductNameNew

About to Refresh...
Name of product after refresh = ProductNameOld1
Name of product after commit = ProductNameOld1

******** Table: Product *******
+-------------+--------------------------------+--------------------------------+------------------------+-------------+
|      ID        |              NAME                   |           DESCRIPTION        |          PRICE           |  SUPPLIERID
+-------------+--------------------------------+--------------------------------+------------------------+-------------+
| 1              | ProductNameOld1            | Description for Product 1  | 2.0                         |             
| 2              | ProductNameOld2            | Description for Product 2  | 22.0                       |             
| 3              | ProductNameOld3            | Description for Product 3  | 30.0                       |             
+-------------+--------------------------------+--------------------------------+------------------------+-------------+
Figure-1.31: Result

                                                                                                              return to top of the exercise



(1.4) Look under the hood of the "HibernateTransactionWithRollback" project


1. Study the Main.java.  Pay special attention to the bold-fonted parts.

import java.util.*;

import java.sql.*;
import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.criterion.*;

public class Main {
   
    public static void main(String[] args) {
       
        // Set up database tables and test data
        HibernateUtil.droptable("drop table Product");
        HibernateUtil.setup("create table Product ( id int, name VARCHAR(30), description VARCHAR(30), price double,supplierId int)");
        prepareTestData();
       
        // Perform the read operation
        SessionFactory factory = new Configuration().configure().buildSessionFactory();
        Session session = factory.openSession();
       
        // Perform a read operation just to verify the product name in the database
        Product product = null;
        product = (Product)session.createQuery("from Product where name='ProductNameOld1'").uniqueResult();
        System.out.println("Name of product retrieved from database = " + product.getName());
       
        // Begin transaction and do Rollback
        System.out.println("Begin transaction...");
        Transaction tx = session.beginTransaction();
        System.out.println("Changing name of product to ProductNameNew...");
        product.setName("ProductNameNew");
       
        System.out.println("\nAbout to do Rollback...");
        System.out.println("Name of product before rollback = " + product.getName());
        tx.rollback();
        System.out.println("After Rollback...");
        System.out.println("Name of product after rollback = " + product.getName());
       
        // Begin transaction and do Refresh and commit
        tx = session.beginTransaction();
        System.out.println("\nAbout to Refresh...");
        session.refresh(product);
        System.out.println("Name of product after refresh = " + product.getName());
        tx.commit();
        System.out.println("Name of product after commit = " + product.getName());
       
        // Display tables
        HibernateUtil.checkData("select * from Product");
       
    }
   
    // Below are utility methods
   
    private static void prepareTestData(){
        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();
       
        Product product1 = new Product("ProductNameOld1","Description for Product 1", 2.0);
        session.save(product1);
       
        Product product12 = new Product("ProductNameOld2","Description for Product 2", 22.0);
        session.save(product12);
       
        Product product2 = new Product("ProductNameOld3", "Description for Product 3", 30.0);
        session.save(product2);
       
        tx.commit();
        HibernateUtil.closeSession();
    }
     
}
Code-1.41:Main.java

                                                                                                              return to top of the exercise


Summary


In this exercise, you have learned how to operation persistence operations within a transactional context.


                                                                                                                  return to the top


Exercise 2: Use a DAO (Data Access Object) pattern

In this exercise, you are going to learn how to use DAO pattern.  DAO pattern separates business logic from persistence code.

  1. Open and run "HibernateSimpleDao" project
  2. Look under the hood of the "HibernateSimpleDao" project
  3. Open and run "HibernateSimpleDaoInterface" project
  4. Look under the hood of the "HibernateSimpleDaoInterface" project

(2.1) Open and run "HibernateSimpleDao" project


1. Open HibernateSimpleDao NetBeans project. 

2. Build and run HibernateSimpleDao project.

Performing create Dao operation....
Perrforming find Dao operation...
Name of the event found = JavaOne conference
Perrforming update Dao operation...
Performing findAll Dao operation...
Number of entries in the database table = 2

******** Table: events *******
+-------------+----------------------+
|     UID       |         NAME           |
+-------------+----------------------+
| 1               | New Conference      
| 2               | Noname conference   
+-------------+----------------------+
Figure-2.11: Result
                                                                                                              return to top of the exercise


(2.2) look under the hood of the "HibernateSimpleDao" project


1. Study the Main.java.  Pay special attention to the bold-fonted parts.  Note that the business logic in the Main.java does not have any persistence technology specific code.

import java.util.*;

import org.hibernate.*;
import org.hibernate.criterion.*;

public class Main {
   
    public static void main(String[] args) {
       
        // Set up database table
        HibernateUtil.droptable("drop table EVENTS");
        HibernateUtil.setup("create table EVENTS ( uid int, name VARCHAR(20), start_Date date, duration int)");
       
        // Create Dao object
        SimpleEventDao eventDao = new SimpleEventDao();
       
        // Perform create Dao operation
        System.out.println("Performing create Dao operation....");
        Event event1 = new Event();
        event1.setName("JavaOne conference");
        eventDao.create(event1);
       
        Event event2 = new Event();
        event2.setName("Noname conference");
        eventDao.create(event2);
       
        // Perform find Dao operation
        System.out.println("Perrforming find Dao operation...");
        Event foundEvent = eventDao.find(event1.getId());
        System.out.println("Name of the event found = " + foundEvent.getName());
       
        // Perform update Dao operation
        System.out.println("Perrforming update Dao operation...");
        event1.setName("New Conference");
        eventDao.update(event1);
       
        // Perform findAll Dao operation
        System.out.println("Performing findAll Dao operation...");
        List eventList = eventDao.findAll();
        System.out.println("Number of entries in the database table = " + eventList.size());
       
        // Display the contents of the database table
        HibernateUtil.checkData("select uid, name from events");
       
    }
   
}
Code-2.21: Main.java

2. Study SimpleEventDao.java.  This class defines SimpleEventDao class which captures all persistence operations - create(), delete(), find(), update(), findAll() - against persistent objects, in this example, Event object.

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.List;


/**
 * The Data Access Object for managing the persistent Events.
 *
 */
public class SimpleEventDao {
    Log log = LogFactory.getLog(SimpleEventDao.class);
    private Session session;
    private Transaction tx;

    public SimpleEventDao() {
        HibernateFactory.buildIfNeeded();
    }

    /**
     * Insert a new Event into the database.
     * @param event
     */
    public void create(Event event) throws DataAccessLayerException {
        try {
            startOperation();
            session.save(event);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }


    /**
     * Delete a detached Event from the database.
     * @param event
     */
    public void delete(Event event) throws DataAccessLayerException {
        try {
            startOperation();
            session.delete(event);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }
    /**
     * Find an Event by its primary key.
     * @param id
     * @return
     */
    public Event find(Long id) throws DataAccessLayerException {
        Event event = null;
        try {
            startOperation();
            event = (Event) session.load(Event.class, id);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            //HibernateFactory.close(session);
        }
        return event;
    }

    /**
     * Updates the state of a detached Event.
     *
     * @param event
     */
    public void update(Event event) throws DataAccessLayerException {
        try {
            startOperation();
            session.update(event);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }

    /**
     * Finds all Events in the database.
     * @return
     */
    public List findAll() throws DataAccessLayerException{
        List events = null;
        try {
            startOperation();
            Query query = session.createQuery("from Event");
            events =  query.list();
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
        return events;
    }

    private void handleException(HibernateException e) throws DataAccessLayerException {
        HibernateFactory.rollback(tx);
        throw new DataAccessLayerException(e);
    }

    private void startOperation() throws HibernateException {
        session = HibernateFactory.openSession();
        tx = session.beginTransaction();
    }

}
Code-2.22: SimpleEventDao.java

3. Study the Event.java.

import java.io.Serializable;
import java.util.Date;
import java.util.Set;
import java.util.LinkedHashSet;

public class Event implements Serializable {
    private Long id;
    private int duration;
    private String name;
    private Date startDate;

    public Event() {

    }

    public Event(String name) {
        this.name = name;
    }

    /**
     * @hibernate.id generator-class="native" column="uid"
     * @return
     */
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    /**
     * @hibernate.property column="name"
     * @return
     */
    public String getName() { return name; }
    public void setName(String name) { this.name = name;   }

    /**
     * @hibernate.property column="start_date"
     * @return
     */
    public Date getStartDate() { return startDate; }
    public void setStartDate(Date startDate) { this.startDate = startDate; }

    /**
     * @hibernate.property column="duration"
     * @return
     */
    public int getDuration() { return duration; }
    public void setDuration(int duration) { this.duration = duration; }

}
Code-2.23: Event.java

4. Study Event.hbm.xml.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
       
<hibernate-mapping >
    <class name="Event" table="events">
        <id name="id" column="uid" type="long">
            <generator class="increment"/>
        </id>
        <property name="name" type="string"/>
        <property name="startDate" column="start_date" type="date"/>
        <property name="duration" type="integer"/>
    </class>
</hibernate-mapping>
Code-2.24: Event.hbm.xml

5. Study hibernate.cfg.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>

        <!-- Database connection settings -->
        <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
        <property name="connection.url">jdbc:derby://localhost:1527/mydatabase</property>
        <property name="connection.username">app</property>
        <property name="connection.password">app</property>

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

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

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

       <!-- Mapping files -->
        <mapping resource="Event.hbm.xml"/>
    </session-factory>

</hibernate-configuration>
Code-2.25: hibernate.cfg.xml
                                                                                                              return to top of the exercise

(2.3) Open and run "HibernateSimpleDaoInterface" project


In general, the DAO object should be accessed through an interface instead of a class.  In this step, you are going to access DAO objects through an interface, SimpleEventDaoInterface.

1. Open HibernateSimpleDaoInterface NetBeans project. 

2. Build and run HibernateSimpleDaoInterface project.  

Performing create Dao operation....
Perrforming find Dao operation...
Name of the event found = JavaOne conference
Perrforming update Dao operation...
Performing findAll Dao operation...
Number of entries in the database table = 2
Perrforming find Dao operation...
Name of the event found = New Conference

******** Table: events *******
+-------------+----------------------+
|     UID       |         NAME           |
+-------------+----------------------+
| 1               | New Conference      
| 2               | Noname conference   
+-------------+----------------------+
Figure-1.11: Result

                                                                                                              return to top of the exercise


(2.4) look under the hood of the "HibernateSimpleDaoInterface" project


1. Study the Main.java.  Pay special attention to the bold-fonted parts.  In this code, the DAO objects are accessed through an interface called SimpleEventDaoInteface.

import java.util.*;

import org.hibernate.*;
import org.hibernate.criterion.*;

public class Main {
   
    public static void main(String[] args) {
       
        // Set up database table
        HibernateUtil.droptable("drop table EVENTS");
        HibernateUtil.setup("create table EVENTS ( uid int, name VARCHAR(20), start_Date date, duration int)");
       
        // Create Dao object and assign it to an interface and use
        // an SimpleEventDao implementation class.
        SimpleEventDaoInterface eventDao = new SimpleEventDao();
       
        // Perform create Dao operation
        System.out.println("Performing create Dao operation....");
        Event event1 = new Event();
        event1.setName("JavaOne conference");
        eventDao.create(event1);
       
        Event event2 = new Event();
        event2.setName("Noname conference");
        eventDao.create(event2);
       
        // Perform find Dao operation
        System.out.println("Perrforming find Dao operation...");
        Event foundEvent = eventDao.find(event1.getId());
        System.out.println("Name of the event found = " + foundEvent.getName());
       
        // Perform update Dao operation
        System.out.println("Perrforming update Dao operation...");
        event1.setName("New Conference");
        eventDao.update(event1);
       
        // Perform findAll Dao operation
        System.out.println("Performing findAll Dao operation...");
        List eventList = eventDao.findAll();
        System.out.println("Number of entries in the database table = " + eventList.size());
       
        // Create Dao object from a different implementation of the same
        // interface and assign it to an interface.

        eventDao = new SimpleEventDaoAnotherImpl();
       
        // Perform find Dao operation
        System.out.println("Perrforming find Dao operation...");
        foundEvent = eventDao.find(event1.getId());
        System.out.println("Name of the event found = " + foundEvent.getName());
       
        // Display the contents of the database table
        HibernateUtil.checkData("select uid, name from events");
       
    }
   
}
Code-2.21: Main.java

2. Study SimpleEventDaoInterface.java. (Code-2.22 below)  This is a Java interface that is created from SimpleEventDao class through "Extract Interface" refactoring.

import java.util.List;
/**
 *
 * @author sang
 */
public interface SimpleEventDaoInterface {
    /**
     * Insert a new Event into the database.
     *
     * @param event
     */
    void create(Event event) throws DataAccessLayerException;

    /**
     * Delete a detached Event from the database.
     *
     * @param event
     */
    void delete(Event event) throws DataAccessLayerException;

    /**
     * Find an Event by its primary key.
     *
     * @param id
     * @return
     */
    Event find(Long id) throws DataAccessLayerException;

    /**
     * Finds all Events in the database.
     *
     * @return
     */
    List findAll() throws DataAccessLayerException;

    /**
     * Updates the state of a detached Event.
     *
     *
     * @param event
     */
    void update(Event event) throws DataAccessLayerException;
   
}
Code-2.22: SimpleEventDaoInterface.java

3. Study SimpleEventDao.java.  The SimpleEventDao class now implements SimpleEventDaoInterface.

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.List;


/**
 * The Data Access Object for managing the persistent Events.
 *
 * @author Patrick Peak
 * @author Nick Heudecker
 */
public class SimpleEventDao implements SimpleEventDaoInterface {
    Log log = LogFactory.getLog(SimpleEventDao.class);
    private Session session;
    private Transaction tx;

    public SimpleEventDao() {
        HibernateFactory.buildIfNeeded();
    }

    /**
     * Insert a new Event into the database.
     * @param event
     */
    public void create(Event event) throws DataAccessLayerException {
        try {
            startOperation();
            session.save(event);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }


    /**
     * Delete a detached Event from the database.
     * @param event
     */
    public void delete(Event event) throws DataAccessLayerException {
        try {
            startOperation();
            session.delete(event);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }
    /**
     * Find an Event by its primary key.
     * @param id
     * @return
     */
    public Event find(Long id) throws DataAccessLayerException {
        Event event = null;
        try {
            startOperation();
            event = (Event) session.load(Event.class, id);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            //HibernateFactory.close(session);
        }
        return event;
    }

    /**
     * Updates the state of a detached Event.
     *
     * @param event
     */
    public void update(Event event) throws DataAccessLayerException {
        try {
            startOperation();
            session.update(event);
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
    }

    /**
     * Finds all Events in the database.
     * @return
     */
    public List findAll() throws DataAccessLayerException{
        List events = null;
        try {
            startOperation();
            Query query = session.createQuery("from Event");
            events =  query.list();
            tx.commit();
        } catch (HibernateException e) {
            handleException(e);
        } finally {
            HibernateFactory.close(session);
        }
        return events;
    }

    private void handleException(HibernateException e) throws DataAccessLayerException {
        HibernateFactory.rollback(tx);
        throw new DataAccessLayerException(e);
    }

    private void startOperation() throws HibernateException {
        session = HibernateFactory.openSession();
        tx = session.beginTransaction();
    }

}
Code-2.23: SimpleEventDao.java

                                                                                                              return to top of the exercise


Summary

In this exercise,  you have learned how to use DAO design pattern in which persistence logic is hidden through a DAO object or a DAO interface.

                                                                                                                        return to the top


Exercise 3: Use different key generation


In this exercise, you are going to learn how to generate key using various schemes.


(3.1) Use "increment" for generating a key


1. Open HibernateHelloWorldKeyByIncrement NetBeans project. 

2. Build and run HibernateHelloWorldKeyByIncrement project.

First person, Id generated via increment = 1
Second person, Id generated via increment = 2

******** Table: Person *******
+-------------+----------------------+
|      ID        |         CNAME         |
+-------------+----------------------+
| 1              | Sang Shin             |
| 2              | Young Shin           |
+-------------+----------------------+
Figure-3.11: Result
                                                                                                              return to top of the exercise


(3.2) look under the hood of the "HibernateHelloWorldKeyByIncrement" project


1. Study the Main.java. (Code-3.21 below)  Pay special attention to the bold-fonted parts.

import org.hibernate.*;
import org.hibernate.cfg.Configuration;

public class Main {
   
    public static void main(String[] args) {
       
        // Set up database tables
        HibernateUtil.droptable("drop table Person");
        HibernateUtil.setup("create table Person ( id int, cname VARCHAR(20))");
       
        // Create SessionFactory and Session object
        SessionFactory sessions = new Configuration().configure().buildSessionFactory();
        Session session = sessions.openSession();
       
        // Perform life-cycle operations under a transaction
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
           
            // Create a Person object and save it
            Person p1 = new Person();
            p1.setName("Sang Shin");
            session.save(p1);
           
            // Create another Person object and save it.
            Person p2 = new Person();
            p2.setName("Young Shin");
            session.save(p2);
           
            // Retrieve the person objects
            Person person = (Person)session. get(Person.class, p1.getId());
            System.out.println("First person, Id generated via increment = " + person.getId());
            person = (Person)session.get(Person.class, p2.getId());
            System.out.println("Second person, Id generated via increment = " + person.getId());
           
            tx.commit();
            tx = null;
        } catch ( HibernateException e ) {
            if ( tx != null ) tx.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
       
        // Display tables
        HibernateUtil.checkData("select * from Person");
             
    }
      
}
Code-3.21: Main.java

2. Study Person.hbm.xml. (Code-3.22 below)  Note that the class attribute of the generator element is set to "increment".

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping
   PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
   
   <class name="Person">
      <id name="id" type="int">
         <generator class="increment"/>
      </id>

      <property name="name" column="cname" type="string"/>
   </class>
  
</hibernate-mapping>
Code-3.22: Person.hbm.xml

                                                                                                                        return to top of the exercise

(3.3) Use "assigned" for generating a key


1. Open HibernateHelloWorldKeyByAssigned NetBeans project. 

2 Build and run HibernateHelloWorldKeyByAssigned project.

First person, Id generated via assigned = 233
Second person, Id generated via assigned = 411

******** Table: Person *******
+-------------+----------------------+
|      ID        |         CNAME         |
+-------------+----------------------+
| 233          | Sang Shin             |
| 411          | Young Shin           |
+-------------+----------------------+
Figure-3.31: Result
                                                                                                              return to top of the exercise


(3.4) look under the hood of the "HibernateHelloWorldKeyByAssigned" project


1. Study the Main.java. (Code-3.41 below)  Pay special attention to the bold-fonted parts.  Note that since you are going to use "assigned" as a way of creating keys, you have to provide the key values yourself through setId() method.

import org.hibernate.*;
import org.hibernate.cfg.Configuration;

public class Main {
   
    public static void main(String[] args) {
       
        // Set up database tables
        HibernateUtil.droptable("drop table Person");
        HibernateUtil.setup("create table Person ( id int, cname VARCHAR(20))");
       
        // Create SessionFactory and Session object
        SessionFactory sessions = new Configuration().configure().buildSessionFactory();
        Session session = sessions.openSession();
       
        // Perform life-cycle operations under a transaction
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
           
            // Create a Person object and save it
            Person p1 = new Person();
            p1.setName("Sang Shin");
           
            // Since the Id generation scheme is now set as "assigned",
            // you have to assign it.
            p1.setId(233);
            session.save(p1);
           
            // Create another Person object and save it.
            Person p2 = new Person();
            p2.setName("Young Shin");
           
            // Since the Id generation scheme is now set as "assigned",
            // you have to assign it.
            p2.setId(411);
            session.save(p2);
           
            // Retrieve the person objects
            Person person = (Person)session. get(Person.class, p1.getId());
            System.out.println("First person, Id generated via assigned = " + person.getId());
            person = (Person)session.get(Person.class, p2.getId());
            System.out.println("Second person, Id generated via assigned = " + person.getId());
           
            tx.commit();
            tx = null;
        } catch ( HibernateException e ) {
            if ( tx != null ) tx.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
       
        // Display tables
        HibernateUtil.checkData("select * from Person");
       
    }
   
}
Code-3.41: Main.java

2. Study Person.hbm.xml. (Code-3.42 below) Note that the class attribute of the generator element is set to "assigned".

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping
   PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
   
   <class name="Person">
      <id name="id" type="int">
         <generator class="assigned"/>
      </id>

      <property name="name" column="cname" type="string"/>
   </class>
  
</hibernate-mapping>
Code-3.42: Person.hbm.xml

                                                                                                                        return to top of the exercise

(3.5) Use "uuid.hex" for generating a key


1. Open HibernateHelloWorldKeyByUUIDHex NetBeans project. 

2. Build and run HibernateHelloWorldKeyByUUIDHex project.

First person, Id generated via uuid.hex = 402882841223d08d011223d08fd00002
Second person, Id generated via uuid.hex = 402882841223d08d011223d08fe00003

******** Table: Person *******
+--------------------------------+----------------------+
|               ID                       |         CNAME        |
+--------------------------------+----------------------+
| 402882841223d08d011223d08fd000 | Sang Shin           
| 402882841223d08d011223d08fe000 | Young Shin          
+--------------------------------+----------------------+
Figure-3.51: Result
                                                                                                              return to top of the exercise


(3.6) look under the hood of the "HibernateHelloWorldKeyByUUIDHex" project


1. Study the Main.java.  (Code-3.61 below) Pay special attention to the bold-fonted parts.

import org.hibernate.*;
import org.hibernate.cfg.Configuration;

public class Main {
   
    public static void main(String[] args) {
       
        // Set up database tables
        HibernateUtil.droptable("drop table Person");
        HibernateUtil.setup("create table Person ( id VARCHAR(50), cname VARCHAR(20))");
       
        // Create SessionFactory and Session object
        SessionFactory sessions = new Configuration().configure().buildSessionFactory();
        Session session = sessions.openSession();
       
        // Perform life-cycle operations under a transaction
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
           
            // Create a Person object and save it
            Person p1 = new Person();
            p1.setName("Sang Shin");
            session.save(p1);
           
            // Create another Person object and save it.
            Person p2 = new Person();
            p2.setName("Young Shin");
            session.save(p2);
           
            // Retrieve the person objects
            Person person = (Person)session.get(Person.class, p1.getId());
            System.out.println("First person, Id generated via uuid.hex = " + person.getId());
            person = (Person)session.get(Person.class, p2.getId());
            System.out.println("Second person, Id generated via uuid.hex = " + person.getId());
           
            tx.commit();
            tx = null;
        } catch ( HibernateException e ) {
            if ( tx != null ) tx.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
       
        // Display tables
        HibernateUtil.checkData("select * from Person");
             
    }
      
}
Code-3.61: Main.java

2. Study Person.hbm.xml.  (Code-3.62 below) Note that the class attribute of the generator element is set to "uuid.hex".

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
   
    <class name="Person">
        <id name="id" type="string" unsaved-value="null">
            <generator class="uuid.hex"/>
        </id>
       
        <property name="name" column="cname" type="string"/>
    </class>
   
</hibernate-mapping>
Code-3.62: Person.hbm.xml

                                                                                                                        return to top of the exercise

Summary


In this exercise, you have learned how to generate key values using different methods - increment, assigned, uuid.hex.


                                                                                                                    return to the top


Exercise 4: Session management


In this exercise, you are going to exercise session management.

(4.1) Build and run "HibernateSessionDisconnectReconnect" project


1. Open HibernateSessionDisconnectReconnect NetBeans project. 

2.  Build and run HibernateSessionDisconnectReconnect project.

Product name = SamSung Phone
Product name = Solaris OS
Product name = Sun workstation
Product name = SamSung Phone
Product name = Solaris OS
Product name = Sun workstation

******** Table: Supplier *******
+-------------+----------------------+
|      ID        |         NAME           |
+-------------+----------------------+
| 1              | Sun Microsystems    
| 2              | SamSung             
+-------------+----------------------+

******** Table: Product *******
+-------------+----------------------+----------------------+------------------------+-------------+
|      ID        |         NAME           |      DESCRIPTION |          PRICE           |  SUPPLIERID
+-------------+----------------------+----------------------+------------------------+-------------+
| 1              | Sun workstation  | Cool machine        | 2.0                        | 1              |
| 2              | Solaris OS            | Coolest OS           | 22.0                      | 1              |
| 3              | SamSung Phone  | Cool phone           | 30.0                      | 2              |
+-------------+----------------------+----------------------+------------------------+-------------+
Figure-5.11: Result
                                                                                                              return to top of the exercise


(4.2) look under the hood of the "HibernateSessionDisconnectReconnect" project


1. Study the Main.java. (Code-5.21 below)  Pay special attention to the bold-fonted parts.

import java.util.*;

import java.sql.*;
import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.criterion.*;

public class Main {
   
    /**
     *
     * @param args
     */
    public static void main(String[] args) {
       
        // Set up database table and test data
        HibernateUtil.droptable("drop table Supplier");
        HibernateUtil.droptable("drop table Product");
        HibernateUtil.setup("create table Supplier ( id int, name VARCHAR(20))");
        HibernateUtil.setup("create table Product ( id int, name VARCHAR(20), description VARCHAR(20), price double,supplierId int)");       
        prepareTestData();
       
        // Create Session object
        SessionFactory factory = new Configuration().configure().buildSessionFactory();
        Session session = factory.openSession();
       
        // Perform a query operation
        Query query = session.createQuery("from Product order by name");
        List list = query.list();
        Iterator i = list.iterator();
        while(i.hasNext()) {
            Product p = (Product)i.next();
            System.out.println("Product name = " + p.getName());
        }
       
        // Disconnect the Session from the current JDBC connection.
        // If the connection was obtained by Hibernate close it and return
        // it to the connection pool; otherwise, return it to the application.
        Connection c = session.disconnect();
       
        // Reconnect to the given JDBC connection. This is used by
        // applications which require long transactions and use
        // application-supplied connections.
        session.reconnect(c);
       
        // Create a Query object
        query = session.createQuery("from Product order by name");
        list = query.list();
        i = list.iterator();
        while(i.hasNext()) {
            Product p = (Product)i.next();
            System.out.println("Product name = " + p.getName());
        }
       
        // Display tables
        HibernateUtil.checkData("select * from Supplier");
        HibernateUtil.checkData("select * from Product");
       
    }
   
    // Below are utility methods

    static public void displaySupplierList(List list) {
        Iterator iter = list.iterator();
        if (!iter.hasNext()) {
            System.out.println("No suppliers to display.");
            return;
        }
        while (iter.hasNext()) {
            Supplier supplier = (Supplier) iter.next();
            String msg = supplier.getName();
            System.out.println(msg);
        }
    }
   
    private static void prepareTestData(){
        Session session = HibernateUtil.currentSession();
       
        Transaction tx = session.beginTransaction();
        Supplier supplier1 = new Supplier();
        supplier1.setName("Sun Microsystems");
        session.save(supplier1);
       
        Supplier supplier2 = new Supplier();
        supplier2.setName("SamSung");
        session.save(supplier2);
       
        Product product1 = new Product("Sun workstation","Cool machine", 2.0);
        product1.setSupplier(supplier1);
        supplier1.getProducts().add(product1);
        session.save(product1);
       
        Product product12 = new Product("Solaris OS","Coolest OS", 22.0);
        product12.setSupplier(supplier1);
        supplier1.getProducts().add(product12);
        session.save(product12);
       
        Product product2 = new Product("SamSung Phone", "Cool phone", 30.0);
        product2.setSupplier(supplier2);
        supplier2.getProducts().add(product2);
        session.save(product2);
       
        tx.commit();
        HibernateUtil.closeSession();
    }
}
Code-5.21: Main.java

                                                                                                                   return to top of the exercise

Summary


In this exercise, you have learned how to perform session management.


                                                                                                                    return to the top


Homework exercise (for people who are taking Sang Shin's "Java EE Programming online course")


1. The homework is to modify the HibernateMyHobby NetBeans project you did as an homework of the "LAB-3513: Building Hibernate Application Step By Step" hands-on lab.  You can name the new project in any way you want but here I am going to call to call it as HibernateMyHobbyDaoInterface.
2. Send the following files to j2eehomeworks@sun.com with Subject as J2EEHomework-hibernatebasics.