Saturday, November 10, 2007

Hibernate Object Relational Mapping

Overview
This tutorial will show you how to create mapping file for a persistent class in more detail by implementing the Billing System that we used to work on it. You may need to review the Introduction to Hibernate World tutorial before reading further.

Background
This tutorial assumes that you already read the Introduction to Hibernate World tutorial already. So you know how to implement the Customer class and it mapping file, how to create Hibernate Configuration file and HibernateUtil helper class and you also have some background about how to persist the data by using Hibernate in the simple way.

Required Software and Dependencies
We still use the same IDE and dependencies JARs as the Introduction to Hibernate World tutorial.

Setting up the Project
We can continue working on this tutorial by using the old project that we just finished on Introduction to Hibernate World tutorial.

Billing System Class Diagram
Let’s take a look at the Billing System class diagram.


Since the Introduction to Hibernate World tutorial show you how to implement Customer class already (we will change it soon). This tutorial will implement the rest of them including the Bill, BillingDetail and Address. Regarding to the class diagram, you will see that each class has an association to another classes. For example Bill class has a one-to-one association to Customer class since we need to know who buys the items and it also have many-to-one association to the BillingDetail class since the customer can buy many of the items in one bill. We will see how to create associations and how to map them in the mapping file later in this tutorial.

Billing System Database Model Diagram
If you don’t familiar with Hibernate and Object Relational Mapping, begin with the Database Model Diagram may be the better way.


These are the database tables that Hibernate will auto-generates for us when we start our application because of we set hbm2ddl.auto attribute to be true in hibernate.cfg.xml file. As you can see there are 4 tables which we map to 4 classes.

First look at the BILL table, it has a foreign key CUSTOMER_ID to CUSTOMER table. If you look back to our class diagram, you will see that the Bill class has customer property too. It means we can map many-to-one association which one table has a foreign key to another table primary key by using the class that related, for example Bill and Customer classes which has CUSTOMER_ID as a foreign key for BILL table and as a primary for CUSTOMER table. There is another many-to-one association for BillDetail and Bill which related by BILL_ID too.

Next let’s see the CUSTOMER table. It has an association to ADDRESS table by ADDRESS_ID. This is one-to-one association since each CUSTOMER should have only one ADDRESS for billing. Please note that, our Customer class and CUSTOMER table isn’t the same as that one in Introduction to Hibernate World anymore because we add new associations to it here.

Finally, it’s a one-to-many association. This association represents one parent has many children. We know that one bill can have many bill details so Bill class will have one-to-many association with BillingDetail class. In Java world, the collection framework is come into play for this situation. Another one-to-many association is Customer and Bill as you can see in our class diagram and database model diagram.

Let’s see each association in more detail about how to create persistent classes and the mapping file.

many-to-one
This is an association from one class to another class by a foreign key from one table is referencing to the primary key of target table. Regarding to our class diagram, the Bill class has a many-to-one association to the Customer class so the Bill class will have customer property. We will show the fragment of code here, don’t worry we will show all of them soon.

public class Bill
{
   …
   private Customer customer;

   …
   public Customer getCustomer()
   {
      return customer;
   }

   public void setCustomer(Customer customer)
   {
      this.customer = customer;
   }
   …
}

As you can see Bill class have customer property, now you can traverse the object graph easily. If you have Bill class and you want to know what the name of the customer is, just get the customer property and look into its properties by getter methods. You need to map this in the Bill.hbm.xml file also. Let’s take a look in it.

<hibernate-mapping>
   <class name="billing.persistence.Bill" table="BILL">
      …
      <many-to-one name="customer" column="CUSTOMER_ID" class="billing.persistence.Customer" cascade="none" />
      …
   </class>
</hibernate-mapping>


We declare the many-to-one association by using many-to-one tag. The name attribute represent the class property. The column represents the foreign key in this table that have an association to another table as a primary key. And the cascade attribute use for transitive persistence. In this file we set it to none because for the Bill class, we just want to know who the customer is. We don’t want to update any customer details. By setting cascade attribute to none, even you change the customer properties, for example the firstName and the lastName, Hibernate won’t update the customer for the value that we change.

one-to-one

A one-to-one seems like the many-to-one. It is one class that has an association to another class by foreign key but they should be an aggregation or a component. For example, regarding to our class diagram, Customer class should have only one address. You can see from the database model diagram that CUSTOMER table has ADDRESS_ID as a foreign key to ADDRESS table.

public class Customer
{
   …

   private Address address;
   …

   public Address getAddress()
   {
      return address;
   }

   public void setAddress(Address address)
   {
      this.address = address;
   }
   …
}

The Customer class has address property as a member. It seems like many-to-one association but we know that the customer should have only one address. The mapping fragment for one-to-one association is showing below.

<hibernate-mapping>
   <class name="billing.persistence.Customer" table="CUSTOMER">
   …
      <one-to-one name="address" class="billing.persistence.Address" cascade="all" />
   …
   </class>
</hibernate-mapping>


The one-to-one element declares that the Customer class has a one-to-one association. The name attribute tells which property is. The class attribute represents the name of an associate class. And the cascade attribute, for this time we set it to all. This means Hibernate will manage all transitive operation for the address attribute. For example, if we set the address value to the Customer, Hibernate will insert the address value to ADDRESS table automatically. If we modify the value, Hibernate will update the address value for us. And if we set it to null, Hibernate will delete the address from Address table.

one-to-many

A one-to-many is a parent-child association that the parent can have many children. We use Collection Framework represents multiple-child in Java world. Regarding to our class diagram, the Bill class has a one-to-many association with the BillingDetial class. And you can see from our database model diagram BILLING_DETAIL table has a foreign key BILL_ID. May be you can tell more that BillingDetail has a many-to-one association with Bill class. Let’s see how to create the persistent class for this association.

public class Bill
{
   …
   private Set billingDetails;
   …

   public Bill ()
   {
      setBillingDetails(new HashSet ());
   }

   public Set getBillingDetails()
   {
      return billingDetails;
   }

   public void setBillingDetails(Set billingDetails)
   {
      this.billingDetails = billingDetails;
   }

   …

}


We use java.util.Set class for maintain the billingDetails property since Bill Class can contain more than one BillingDetail. And we have instantiated the HashSet for the billDetails property in Bill constructor.

You can use these collections for mapping with one-to-many element depends on your requirement.

  • java.util.Collection can be mapped with bag or idbag element and initial with java.util.ArrayList. Duplicate objects are allowed, object order isn’t preserved.

  • java.util.Set can be mapped with set element and initial with java.util.HashSet. Duplicate objects aren’t allowed and object order isn’t preserved.

  • java.util.SortedSet can be mapped with set element and initial with java.util.TreeSet. We can assign sort attribute with a comparator or just using in-memory sorting. Duplicate object aren’t allowed and object order is preserved.

  • java.util.List can be mapped with list element and initial it with java.util.ArrayList. It is positioning each object with an index.

  • java.util.Map can be mapped with map element and using java.util.HashMap for initialization. It’s a key-value pair’s collection.

  • java.util.SortedMap can be mapped with map element and using java.util.TreeMap for initialization. The sort attribute can be a comparator or natural in-memory sorting.

Next, we need to map the persistent class in the mapping file. The fragment below shows how to map one-to-many in the Bill.hbm.xml file.

<hibernate-mapping>
   <class name="billing.persistence.Bill" table="BILL">
      …
      <set name="billingDetails" cascade="all-delete-orphan">
         <key column="BILL_ID"/>
         <one-to-many class="billing.persistence.BillingDetail"/>
      </set>
      …
   </class>
</hibernate-mapping>


The set element declares that we use java.util.Set to implement this one-to-many property. The name attribute for telling what the property’s name is. And the cascade attribute, we choose all-delete-orphan this time because we want Hibernate manage all transitive persistence for billingDetails property. And for delete-orphan it means Hibernate will delete the record from the table if it was removed from the collection.

The key element have a column attribute to tell about the child’s foreign key in this case the foreign key of the BILLING_DETAIL table which map to the parent’s primary.

And one-to-many element has a class property to tell what Java class for this one-to-many collection.

Implementing Persistent Classes and the mapping files

Now it’s time to review all the classes and mapping files. Let’s begin with the easiest one, the Address class.
package billing.persistence;

package billing.persistence;

public class Address
{
   private Long addressId;
   private String addressNo;
   private String streetName;
   private String city;
   private String province;
   private String country;

   public Address()
   {
   }

   public Long getAddressId()
   {
      return addressId;
   }

   public void setAddressId(Long addressId)
   {
      this.addressId = addressId;
   }

   public String getAddressNo()
   {
      return addressNo;
   }

   public void setAddressNo(String addressNo)
   {
      this.addressNo = addressNo;
   }

   public String getStreetName()
   {
      return streetName;
   }

   public void setStreetName(String streetName)
   {
      this.streetName = streetName;
   }

   public String getCity()
   {
      return city;
   }

   public void setCity(String city)
   {
      this.city = city;
   }

   public String getProvince()
   {
      return province;
   }

   public void setProvince(String province)
   {
      this.province = province;
   }

   public String getCountry()
   {
      return country;
   }

   public void setCountry(String country)
   {
      this.country = country;
   }

   @Override
   public String toString()
   {
      StringBuilder stringBuilder = new StringBuilder ();
      stringBuilder.append(getAddressNo());
      stringBuilder.append(", ");
      stringBuilder.append(getStreetName());
      stringBuilder.append(", ");
      stringBuilder.append(getCity());
      stringBuilder.append(", ");
      stringBuilder.append(getProvince());
      stringBuilder.append(", ");
      stringBuilder.append(getCountry());

      return stringBuilder.toString();
   }
}


Nothing special for the Address class, it’s just a class that contains the address information including addressNo, streetName, city, province and country. Notice that we have override the toString method we will use this method for getting the address detail later in the Customer class. You will see the Address.hbm.xml mapping file below.

<?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="billing.persistence.Address" table="ADDRESS">
      <id name="addressId" column="ADDRESS_ID" type="long">
         <generator class="native"/>
      </id>
      <property name="addressNo" column="ADDRESS_NO" type="string" />
      <property name="streetName" column="STREET_NAME" type="string" />
      <property name="city" column="CITY" type="string" />
      <property name="province" column="PROVINCE" type="string" />
      <property name="country" column="COUNTRY" type="string" />
   </class>
</hibernate-mapping>

As you imagine, just the plain mapping file that map each class property to the column of database table. Next, let’s move to the Customer class.

package billing.persistence;

public class Customer
{
   private Long customerId;
   private String firstName;
   private String lastName;
   private Address address;

   public Customer ()
   {
   }

   public Long getCustomerId()
   {
      return customerId;
   }

   public void setCustomerId(Long customerId)
   {
      this.customerId = customerId;
   }

   public String getFirstName()
   {
      return firstName;
   }

   public void setFirstName(String firstName)
   {
      this.firstName = firstName;
   }

   public String getLastName()
   {
      return lastName;
   }

   public void setLastName(String lastName)
   {
      this.lastName = lastName;
   }

   public Address getAddress()
   {
      return address;
   }

   public void setAddress(Address address)
   {
      this.address = address;
   }

   @Override
   public String toString()
   {
      StringBuilder stringBuilder = new StringBuilder ();
      stringBuilder.append(getFirstName());
      stringBuilder.append(" ");
      stringBuilder.append(getLastName());
      stringBuilder.append(" whose address is ");
      stringBuilder.append(getAddress().toString());

      return stringBuilder.toString();
   }

}


You can see that the Customer class has address property which we already discuss in the one-to-one section already. Again, we have override the toString method. It will be useful when we want to monitoring or debugging the value in the Customer class. The Customer.hbm.xml is below.

<?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="billing.persistence.Customer" table="CUSTOMER">
      <id name="customerId" column="CUSTOMER_ID" type="long">
         <generator class="native"/>
      </id>
      <property name="firstName" column="FIRST_NAME" type="string" />
      <property name="lastName" column="LAST_NAME" type="string" />
      <one-to-one name="address" class="billing.persistence.Address" cascade="all" />
   </class>
</hibernate-mapping>

We already discuss about one-to-one element in section one-to-one already and the rest of file is just mapping properties to the columns. The Customer class also has a one-to-many association with the Bill class but we don’t map for it here because this tutorial just wants to show how to mapping associations in the simple way. Anyway we can map the one-to-many association to the Bill class later easily. We will move to the Bill class next.

package billing.persistence;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

public class Bill
{
   private Long billId;
   private Customer customer;
   private Set billingDetails;
   private Date billingDate;

   public Bill ()
   {
      setBillingDetails(new HashSet ());
   }

   public Long getBillId()
   {
      return billId;
   }

   public void setBillId(Long billId)
   {
      this.billId = billId;
   }

   public Customer getCustomer()
   {
      return customer;
   }

   public void setCustomer(Customer customer)
   {
      this.customer = customer;
   }

   public Set getBillingDetails()
   {
      return billingDetails;
   }

   public void setBillingDetails(Set billingDetails)
   {
      this.billingDetails = billingDetails;
   }

   public Date getBillingDate()
   {
      return billingDate;
   }

   public void setBillingDate(Date billingDate)
   {
      this.billingDate = billingDate;
   }

   @Override
   public String toString()
   {
      StringBuilder stringBuilder = new StringBuilder ();

      stringBuilder.append("Bill created on ");
      stringBuilder.append(getBillingDate());
      stringBuilder.append(" for ");
      stringBuilder.append(getCustomer().toString());
      stringBuilder.append(" and bought,\n");

      for (BillingDetail billingDetail : billingDetails)
      {
         stringBuilder.append(billingDetail);
         stringBuilder.append("\n");
      }

      return stringBuilder.toString();
   }

}


The Bill class represents the bill for the customer. This class has a customer property since the bill should have a detail about the customer, who bought the items. The billingDate property represents what date that the bill was created. And since the customer can buy many items at one time, so the bill can have many billing details (one billing detail represents the detail about one item including the item name, price per unit and the amount of the item that the customer bought). That’s why we use Collection for the BillingDetail class.

Last, we override the toString method. It will create the detail about this bill including billing date, customer name and all the items detail that customer bought by calling BillingDetail’s toString method. We will see toString method of BillingDetail very soon. Right now, concentrate on Bill.hbm.xml file.

<?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="billing.persistence.Bill" table="BILL">
      <id name="billId" column="BILL_ID" type="long">
         <generator class="native"/>
      </id>
      <many-to-one name="customer" column="CUSTOMER_ID" class="billing.persistence.Customer" cascade="none" />
      <set name="billingDetails" cascade="all-delete-orphan">
         <key column="BILL_ID"/>
         <one-to-many class="billing.persistence.BillingDetail"/>
      </set>
      <property name="billingDate" column="BILLING_DATE" type="date" />
   </class>
</hibernate-mapping>


You can see the many-to-one association to the Customer class. Next you will see the set element for billingDetials property which we know it is a one-to-many property and we discussed already. The billingDate property represents the date and time that the bill was created.

Finally we will see the last class for now, the BillDetail class.

package billing.persistence;

import java.math.BigDecimal;

public class BillingDetail
{
   private Long billingDetailId;
   private Bill bill;
   private String itemName;
   private BigDecimal pricePerUnit;
   private Long amount;

   public BillingDetail ()
   {
   }

   public Long getBillingDetailId()
   {
      return billingDetailId;
   }

   public void setBillingDetailId(Long billingDetailId)
   {
      this.billingDetailId = billingDetailId;
   }

   public Bill getBill()
   {
      return bill;
   }

   public void setBill(Bill bill)
   {
      this.bill = bill;
   }

   public String getItemName()
   {
      return itemName;
   }

   public void setItemName(String itemName)
   {
      this.itemName = itemName;
   }

   public BigDecimal getPricePerUnit()
   {
      return pricePerUnit;
   }

   public void setPricePerUnit(BigDecimal pricePerUnit)
   {
      this.pricePerUnit = pricePerUnit;
   }

   public Long getAmount()
   {
      return amount;
   }

   public void setAmount(Long amount)
   {
      this.amount = amount;
   }

   @Override
   public String toString()
   {
      StringBuilder stringBuilder = new StringBuilder ();

      stringBuilder.append(getAmount());
      stringBuilder.append(" of ");
      stringBuilder.append(getItemName());
      stringBuilder.append("(s), total price ");
      stringBuilder.append(getPricePerUnit().multiply(new BigDecimal(getAmount())));
      stringBuilder.append(".");

      return stringBuilder.toString();
   }

   @Override
   public boolean equals(Object obj)
   {
      if (obj == null) return false;
      if (this == obj) return true;
      if (!(obj instanceof BillingDetail)) return false;

      BillingDetail castedObj = (BillingDetail) obj;
      if (this.getBillingDetailId() != null
         && this.getBillingDetailId().equals(castedObj.getBillingDetailId()))
      {
         return true;
      }

      return super.equals(obj);
   }

   @Override
   public int hashCode()
   {
      if (this.getBillingDetailId() == null)
      {
         return super.hashCode();
      }

      return this.getBillingDetailId().hashCode();
   }

}


Not too hard since we know all the associations already. It has a many-to-one to the Bill class. The itemName, pricePerUnit and amount just the properties map to the columns. And we override the toString method as always to extract the detail of this class. Further more we override the equal and hashCode method. In fact, it is a good practice to override equal and hashCode method for every persistent class. But for this tutorial to keep it simple, we choose to override these methods only the class that participate with Collection Framework only since the Collection Framework will use these 2 methods for check the equality or the order. The way that we implements these 2 methods just depends on its primary key which is the billingDetailId property as you can see from the source code above.

It’s time for the last mapping file, BillingDetail.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="billing.persistence.BillingDetail" table="BILLING_DETAIL">
      <id name="billingDetailId" column="BILLING_DETAIL_ID" type="long">
         <generator class="native"/>
      </id>
      <many-to-one name="bill" column="BILL_ID" class="billing.persistence.Bill" cascade="none" />
      <property name="itemName" column="ITEM_NAME" type="string" />
      <property name="pricePerUnit" column="PRICE_PER_UNIT" type="big_decimal" />
      <property name="amount" column="AMOUNT" type="long" />
   </class>
</hibernate-mapping>


One new thing here is the Hibernate Type big_decimal for the pricePerUnit property. As you guess, this Hibernate Type will be map to java.math.BigDecimal in the Java World.

Hibernate Configuration

We have more classes in this tutorial so we need to add more mapping resource. And here’s the hibernate.cfg.xml that modified already.

<?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="connection.driver_class">org.hsqldb.jdbcDriver>/property>
      <property name="connection.url">jdbc:hsqldb:mem:localhost>/property>
      <property name="connection.username">sa>/property>
      <property name="connection.password">>/property>
      <property name="dialect">org.hibernate.dialect.HSQLDialect>/property>
      <property name="show_sql">true>/property>
      <property name="hbm2ddl.auto">create>/property>
      <mapping resource="billing/persistence/Customer.hbm.xml" />
      <mapping resource="billing/persistence/Address.hbm.xml" />
      <mapping resource="billing/persistence/Bill.hbm.xml" />
      <mapping resource="billing/persistence/BillingDetail.hbm.xml" />
   </session-factory>
</hibernate-configuration>


You can see that we add Address.hbm.xml, Bill.hbm.xml and BillingDetail.hbm.xml by mapping element.

Investigate the object graph and transitive persist

After create persistent classes, mapping files and add mapping resource to Hibernate Configuration file, it’s time to learn how to use and monitoring how Hibernate working with the associations. Now modify the Main class which is the class that everything will begin here.
package billing.demo;

import java.math.BigDecimal;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.Transaction;

import billing.persistence.Address;
import billing.persistence.Bill;
import billing.persistence.BillingDetail;
import billing.persistence.Customer;
import billing.util.HibernateUtil;

public class Main
{
   @SuppressWarnings("unchecked")
   public static void main (String [] args)
   {
      try
      {
         System.out.println ("Create Customer instance...");
         Session session = HibernateUtil.getSessionFactory().openSession();
         Transaction tx = session.beginTransaction();
         Customer customer = new Customer ();
         customer.setFirstName("John");
         customer.setLastName("Doe");

         System.out.println ("Create Address instance...");
         Address address = new Address ();
         address.setAddressNo("100");
         address.setStreetName("Street");
         address.setCity("City");
         address.setProvince("Province");
         address.setCountry("Country");

         System.out.println ("Assign Address to Customer...");
         customer.setAddress(address);

         System.out.println ("Persist Customer...");
         session.save(customer);
         tx.commit();
         session.close();

         System.out.println ("Create Bill instance...");
         Bill bill = new Bill ();
         bill.setCustomer(customer);
         bill.setBillingDate(new Date ());

         System.out.println ("Create Book Billing Detail intance...");
         BillingDetail bookBillingDetail = new BillingDetail ();
         bookBillingDetail.setBill(bill);
         bookBillingDetail.setItemName("Book");
         bookBillingDetail.setPricePerUnit(new BigDecimal("3.45"));
         bookBillingDetail.setAmount(new Long (10));

         System.out.println ("Create Pen Billing Detail intance...");
         BillingDetail penBillingDetail = new BillingDetail ();
         penBillingDetail.setBill(bill);
         penBillingDetail.setItemName("Pen");
         penBillingDetail.setPricePerUnit(new BigDecimal("12.00"));
         penBillingDetail.setAmount(new Long (3));

         System.out.println ("Add Book Billing Detail to the Bill...");
         bill.getBillingDetails().add(bookBillingDetail);

         System.out.println ("Add Pen Billing Detail to the Bill...");
         bill.getBillingDetails().add(penBillingDetail);

         session = HibernateUtil.getSessionFactory().openSession();
         tx = session.beginTransaction();
         System.out.println ("Insert Bill...");
         session.save(bill);
         tx.commit();
         session.close();

         System.out.println ("Query Bill data...");
         Long billId = bill.getBillId();
         session = HibernateUtil.getSessionFactory().openSession();
         bill = (Bill)session.get(Bill.class, billId);
         System.out.println (bill);
         session.close();

         System.out.println ("Modify Customer for testing transitive persist with none value...");
         customer.setFirstName("Joe");
         customer.setLastName("Ray");

         System.out.println ("Optional assign Customer to Bill, just to make sure...");
         bill.setCustomer(customer);

         System.out.println ("Remove Pen Billing Detail from Bill...");
         bill.getBillingDetails().remove(penBillingDetail);

         session = HibernateUtil.getSessionFactory().openSession();
         tx = session.beginTransaction();
         System.out.println ("Update Bill...");
         session.update(bill);
         tx.commit();
         session.close();

         System.out.println ("Query Bill data...");
         session = HibernateUtil.getSessionFactory().openSession();
         bill = (Bill)session.get(Bill.class, billId);
         System.out.println (bill);
         session.close();
      }
      finally
      {
         HibernateUtil.getSessionFactory().close();
      }
   }
}


Before running the Main class, please check that your project should contains all the files like this.



To run the Main class, right click on Main.java, choose Run As → Java Application. You will see the Console window at the bottom of the screen. If you can’t find the Console window, click on the Window drop down menu → Show View → Console.

After running the Main class, you should see some text like this,

Create Customer instance...
Create Address instance...
Assign Address to Customer...
Persist Customer...
Hibernate: insert into CUSTOMER (CUSTOMER_ID, FIRST_NAME, LAST_NAME) values (null, ?, ?)
Hibernate: call identity()
Hibernate: insert into ADDRESS (ADDRESS_ID, ADDRESS_NO, STREET_NAME, CITY, PROVINCE, COUNTRY) values (null, ?, ?, ?, ?, ?)
Hibernate: call identity()
Create Bill instance...
Create Book Billing Detail intance...
Create Pen Billing Detail intance...
Add Book Billing Detail to the Bill...
Add Pen Billing Detail to the Bill...
Insert Bill...
Hibernate: insert into BILL (BILL_ID, CUSTOMER_ID, BILLING_DATE) values (null, ?, ?)
Hibernate: call identity()
Hibernate: insert into BILLING_DETAIL (BILLING_DETAIL_ID, BILL_ID, ITEM_NAME, PRICE_PER_UNIT, AMOUNT) values (null, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into BILLING_DETAIL (BILLING_DETAIL_ID, BILL_ID, ITEM_NAME, PRICE_PER_UNIT, AMOUNT) values (null, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: update BILLING_DETAIL set BILL_ID=? where BILLING_DETAIL_ID=?
Hibernate: update BILLING_DETAIL set BILL_ID=? where BILLING_DETAIL_ID=?
Query Bill data...
Hibernate: select bill0_.BILL_ID as BILL1_2_0_, bill0_.CUSTOMER_ID as CUSTOMER2_2_0_, bill0_.BILLING_DATE as BILLING3_2_0_ from BILL bill0_ where bill0_.BILL_ID=?
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_1_, customer0_.FIRST_NAME as FIRST2_0_1_, customer0_.LAST_NAME as LAST3_0_1_, address1_.ADDRESS_ID as ADDRESS1_1_0_, address1_.ADDRESS_NO as ADDRESS2_1_0_, address1_.STREET_NAME as STREET3_1_0_, address1_.CITY as CITY1_0_, address1_.PROVINCE as PROVINCE1_0_, address1_.COUNTRY as COUNTRY1_0_ from CUSTOMER customer0_ left outer join ADDRESS address1_ on customer0_.CUSTOMER_ID=address1_.ADDRESS_ID where customer0_.CUSTOMER_ID=?
Hibernate: select billingdet0_.BILL_ID as BILL2_1_, billingdet0_.BILLING_DETAIL_ID as BILLING1_1_, billingdet0_.BILLING_DETAIL_ID as BILLING1_3_0_, billingdet0_.BILL_ID as BILL2_3_0_, billingdet0_.ITEM_NAME as ITEM3_3_0_, billingdet0_.PRICE_PER_UNIT as PRICE4_3_0_, billingdet0_.AMOUNT as AMOUNT3_0_ from BILLING_DETAIL billingdet0_ where billingdet0_.BILL_ID=?
Bill created on 2007-11-10 for John Doe whose address is 100, Street, City, Province, Country and bought,
10 of Book(s), total price 34.50.
3 of Pen(s), total price 36.00.

Modify Customer for testing transitive persist with none value...
Optional assign Customer to Bill, just to make sure...
Remove Pen Billing Detail from Bill...
Update Bill...
Hibernate: update BILL set CUSTOMER_ID=?, BILLING_DATE=? where BILL_ID=?
Hibernate: update BILLING_DETAIL set BILL_ID=?, ITEM_NAME=?, PRICE_PER_UNIT=?, AMOUNT=? where BILLING_DETAIL_ID=?
Hibernate: update BILLING_DETAIL set BILL_ID=null where BILL_ID=? and BILLING_DETAIL_ID=?
Hibernate: delete from BILLING_DETAIL where BILLING_DETAIL_ID=?
Query Bill data...
Hibernate: select bill0_.BILL_ID as BILL1_2_0_, bill0_.CUSTOMER_ID as CUSTOMER2_2_0_, bill0_.BILLING_DATE as BILLING3_2_0_ from BILL bill0_ where bill0_.BILL_ID=?
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_1_, customer0_.FIRST_NAME as FIRST2_0_1_, customer0_.LAST_NAME as LAST3_0_1_, address1_.ADDRESS_ID as ADDRESS1_1_0_, address1_.ADDRESS_NO as ADDRESS2_1_0_, address1_.STREET_NAME as STREET3_1_0_, address1_.CITY as CITY1_0_, address1_.PROVINCE as PROVINCE1_0_, address1_.COUNTRY as COUNTRY1_0_ from CUSTOMER customer0_ left outer join ADDRESS address1_ on customer0_.CUSTOMER_ID=address1_.ADDRESS_ID where customer0_.CUSTOMER_ID=?
Hibernate: select billingdet0_.BILL_ID as BILL2_1_, billingdet0_.BILLING_DETAIL_ID as BILLING1_1_, billingdet0_.BILLING_DETAIL_ID as BILLING1_3_0_, billingdet0_.BILL_ID as BILL2_3_0_, billingdet0_.ITEM_NAME as ITEM3_3_0_, billingdet0_.PRICE_PER_UNIT as PRICE4_3_0_, billingdet0_.AMOUNT as AMOUNT3_0_ from BILLING_DETAIL billingdet0_ where billingdet0_.BILL_ID=?
Bill created on 2007-11-10 for John Doe whose address is 100, Street, City, Province, Country and bought,
10 of Book(s), total price 34.50.


A little bit long but we can understand easily by working on it as a unit of work.

Create Customer instance...
Create Address instance...
Assign Address to Customer...
Persist Customer...
Hibernate: insert into CUSTOMER (CUSTOMER_ID, FIRST_NAME, LAST_NAME) values (null, ?, ?)
Hibernate: call identity()
Hibernate: insert into ADDRESS (ADDRESS_ID, ADDRESS_NO, STREET_NAME, CITY, PROVINCE, COUNTRY) values (null, ?, ?, ?, ?, ?)
Hibernate: call identity()


We create the Customer instance, set its properties value. Then we create Address instance and set the values for it. As you know Customer class also have address property, so we assign the Address instance that we just create to Customer. Next we call the session.save method to tell Hibernate to insert the Customer. Hibernate will create 2 insert SQL statement for Customer and Address even we call save and pass only Customer instance. That’s because we set cascade attribute to all as we discussed sometime ago. Hibernate manage transitive persist for the address property in Customer class for us.

Create Bill instance...
Create Book Billing Detail intance...
Create Pen Billing Detail intance...
Add Book Billing Detail to the Bill...
Add Pen Billing Detail to the Bill...
Insert Bill...
Hibernate: insert into BILL (BILL_ID, CUSTOMER_ID, BILLING_DATE) values (null, ?, ?)
Hibernate: call identity()
Hibernate: insert into BILLING_DETAIL (BILLING_DETAIL_ID, BILL_ID, ITEM_NAME, PRICE_PER_UNIT, AMOUNT) values (null, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: insert into BILLING_DETAIL (BILLING_DETAIL_ID, BILL_ID, ITEM_NAME, PRICE_PER_UNIT, AMOUNT) values (null, ?, ?, ?, ?)
Hibernate: call identity()
Hibernate: update BILLING_DETAIL set BILL_ID=? where BILLING_DETAIL_ID=?
Hibernate: update BILLING_DETAIL set BILL_ID=? where BILLING_DETAIL_ID=?


Next we create Bill instance, set its properties value. Then create BillingDetail instance for both Book and Pen item. We add these items by calling add method from billingDetails property since it is an instance of the java.util.Set. Now call session.save method for persist the Bill. Hibernate will generate insert SQL statement for Bill class. And we also set cascade attribute to all for billingDetails property so Hibernate manage the transitive persistent for us again. It creates 2 insert SQL statements and 2 update SQL statements for 2 billingDetails that we just add.

Query Bill data...
Hibernate: select bill0_.BILL_ID as BILL1_2_0_, bill0_.CUSTOMER_ID as CUSTOMER2_2_0_, bill0_.BILLING_DATE as BILLING3_2_0_ from BILL bill0_ where bill0_.BILL_ID=?
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_1_, customer0_.FIRST_NAME as FIRST2_0_1_, customer0_.LAST_NAME as LAST3_0_1_, address1_.ADDRESS_ID as ADDRESS1_1_0_, address1_.ADDRESS_NO as ADDRESS2_1_0_, address1_.STREET_NAME as STREET3_1_0_, address1_.CITY as CITY1_0_, address1_.PROVINCE as PROVINCE1_0_, address1_.COUNTRY as COUNTRY1_0_ from CUSTOMER customer0_ left outer join ADDRESS address1_ on customer0_.CUSTOMER_ID=address1_.ADDRESS_ID where customer0_.CUSTOMER_ID=?
Hibernate: select billingdet0_.BILL_ID as BILL2_1_, billingdet0_.BILLING_DETAIL_ID as BILLING1_1_, billingdet0_.BILLING_DETAIL_ID as BILLING1_3_0_, billingdet0_.BILL_ID as BILL2_3_0_, billingdet0_.ITEM_NAME as ITEM3_3_0_, billingdet0_.PRICE_PER_UNIT as PRICE4_3_0_, billingdet0_.AMOUNT as AMOUNT3_0_ from BILLING_DETAIL billingdet0_ where billingdet0_.BILL_ID=?
Bill created on 2007-11-10 for John Doe whose address is 100, Street, City, Province, Country and bought,
10 of Book(s), total price 34.50.
3 of Pen(s), total price 36.00.


After inserting the Bill class, we try to query it by using session.get method and passing the billId for getting the data. You can see that Hibernate generate 3 select SQL statements for Bill, Customer and BillingDetail. And then we call bill.toString method by using System.out.println to see what we get from the database. You can see that it displays the detail of bill, customer, address and all items that the customer bought from us.

Modify Customer for testing transitive persist with none value...
Optional assign Customer to Bill, just to make sure...
Remove Pen Billing Detail from Bill...
Update Bill...
Hibernate: update BILL set CUSTOMER_ID=?, BILLING_DATE=? where BILL_ID=?
Hibernate: update BILLING_DETAIL set BILL_ID=?, ITEM_NAME=?, PRICE_PER_UNIT=?, AMOUNT=? where BILLING_DETAIL_ID=?
Hibernate: update BILLING_DETAIL set BILL_ID=null where BILL_ID=? and BILLING_DETAIL_ID=?
Hibernate: delete from BILLING_DETAIL where BILLING_DETAIL_ID=?


Now we try to modify the customer firstName and lastName and assign it to the Bill class. But remember that, the customer property in Bill class using none for cascade value. It means Hibernate won’t handle any transitive persist for this property. So you won’t see anything happened for the customer details here.

We also remove Pen Billing Detail from the billingDetails property. Anyway this time we set all-delete-orphan for cascade attribute, so Hibernate will remove it for us. You can see that there are some update SQL statements and delete SQL statement.

Query Bill data...
Hibernate: select bill0_.BILL_ID as BILL1_2_0_, bill0_.CUSTOMER_ID as CUSTOMER2_2_0_, bill0_.BILLING_DATE as BILLING3_2_0_ from BILL bill0_ where bill0_.BILL_ID=?
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_1_, customer0_.FIRST_NAME as FIRST2_0_1_, customer0_.LAST_NAME as LAST3_0_1_, address1_.ADDRESS_ID as ADDRESS1_1_0_, address1_.ADDRESS_NO as ADDRESS2_1_0_, address1_.STREET_NAME as STREET3_1_0_, address1_.CITY as CITY1_0_, address1_.PROVINCE as PROVINCE1_0_, address1_.COUNTRY as COUNTRY1_0_ from CUSTOMER customer0_ left outer join ADDRESS address1_ on customer0_.CUSTOMER_ID=address1_.ADDRESS_ID where customer0_.CUSTOMER_ID=?
Hibernate: select billingdet0_.BILL_ID as BILL2_1_, billingdet0_.BILLING_DETAIL_ID as BILLING1_1_, billingdet0_.BILLING_DETAIL_ID as BILLING1_3_0_, billingdet0_.BILL_ID as BILL2_3_0_, billingdet0_.ITEM_NAME as ITEM3_3_0_, billingdet0_.PRICE_PER_UNIT as PRICE4_3_0_, billingdet0_.AMOUNT as AMOUNT3_0_ from BILLING_DETAIL billingdet0_ where billingdet0_.BILL_ID=?
Bill created on 2007-11-10 for John Doe whose address is 100, Street, City, Province, Country and bought,
10 of Book(s), total price 34.50.


Finally, we query the Bill data again. You can see that the customer firstName and lastName didn’t change because cascade value is none. And the Pen Billing Detail was gone since we remove it and using all-delete-orphan for this property.

Summery

Congratulations, now you know how to map associations to the persistent class and mapping file. You also learn some basic about transitive persist which is a great part in Hibernate. Anyway this tutorial is just an introduction for a basic concept to make you understand Hibernate easier. You need to read more because there are plenty of concepts that you still not know. I recommend that you should read all of http://www.hibernate.org/hib_docs/v3/reference/en/html_single or just review it when you need to understand something clearly. We will see how to use Hibernate in the real world web application soon.

Saturday, November 3, 2007

Introduction to Hibernate World

Overview
This tutorial is an introduction to Hibernate World. It will show you how to configure Hibernate by the XML file, how to implement a persistent class in JavaBean and connect with the HSQL DB which is a 100% java based SQL DBMS.

Required Software and Dependencies
First of all, you need to set up the environment for this tutorial. Here’s a list of the software and dependencies that you need to download.


Although this tutorial is making for the new Users, we won’t cover how to install Java SE, and Eclipse IDE. If you have some problems about how to make them working together, please try to search for the solutions from the Internet. There are plenty of them.

Project Overview

Let’s take a look in the Class Diagram. It will make you understand more clearly about what we are going to do.

Well, simple enough for the beginning. We will implement the Billing System. There is a customer, who buys the items and then we will create the bill. But this time just concentrate on the Customer class only. We will cover the other classes in the next tutorial. The Customer should have customerId property, which is an identity to make each Customer to be unique. Normally the identity property is a surrogate key. It means nothing to the business, just for referencing to the Customer class in the application only. The other properties for the Customer are firstName and lastName which are straightforward.

Setting up the Project
  • Create Java Project from Eclipse’s Panel by click on File → New → Java Project. Then, name the project as BillingSystem.

  • In the Java Setting window, click on Libraries Tab. Then add the needed libraries by clicking on Add External JARs button. You can find these JARs from Hibernate Core and HSQL DB that we have downloaded before. This is a list of JARs that we need for our project

    • hibernate3.jar

    • antlr.jar

    • asm.jar

    • asm-attrs.jar

    • c3p0.jar

    • cglib.jar

    • dom4j.jar

    • jta.jar

    • hsqldb.jar

    • commons-collections.jar

    • commons-logging.jar

  • After adding External JARs, you need to add JRE System Library. In the Java Setting Window, click on Add Library Button then choose JRE System Library. You may use Workspace default JRE or specify Alternate JRE yourself. Next click on Finish button.

  • Click on OK button. BillingSystem project should be display in the Package Explorer on the Left Side of the screen.

  • Right Click on BillingSystem, go to New → Source Folder, name the Source Folder as src, then click on Finish button.

Finally, your Eclipse IDE should have the project looks like this,


The Persistent Class
The Persistent Class is just a simple JavaBean class with the properties that map to the Database Table. Let’s create the Cutomer class. Right click on the src folder, choose New → Class, put billing.persistence as a package and name the class as Customer.

package billing.persistence;

public class Customer
{
   private Long customerId;
   private String firstName;
   private String lastName;

   public Customer ()
   {
   }

   public Long getCustomerId()
   {
      return customerId;
   }

   public void setCustomerId(Long customerId)
   {
      this.customerId = customerId;
   }

   public String getFirstName()
   {
      return firstName;
   }

   public void setFirstName(String firstName)
   {
      this.firstName = firstName;
   }

   public String getLastName()
   {
      return lastName;
   }

   public void setLastName(String lastName)
   {
      this.lastName = lastName;
   }

   @Override
   public String toString()
   {
      return "[customerId:" + getCustomerId() + "], [firstName:" + getFirstName() + "], [lastName:" + getLastName() + "]";
   }
}

The Customer class is following the JavaBean naming convention. Notice that, we also override the toString() method so it will be easy to monitor what value inside our JavaBean when debugging by calling System.out.println method.

Mapping File
The mapping file is an XML file that tells Hibernate what database table maps to the JavaBean class and what columns map to the JavaBean’s properties. It’s a good practice to keep the mapping file in the same folder where its JavaBean class is. So you should create Customer.hbm.xml by right click on billing.persistence package, then choose New → File and name the file as Customer.hbm.xml. Here’s the detail of the Customer mapping file.

<?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="billing.persistence.Customer" table="CUSTOMER">
   <id name="customerId" column="CUSTOMER_ID" type="long">
      <generator class="native"/>
   </id>
   <property name="firstName" column="FIRST_NAME" type="string" />
   <property name="lastName" column="LAST_NAME" type="string" />
   </class>
</hibernate-mapping>
The mapping file begins with hibernate-mapping tag. Next is the class tag, this tag tells that the instance of class billing.persistence.Customer represents one record of CUSTOMER table. The id tag represents the identity property. From Customer.hbm.xml, it means column CUSTOMER_ID is a Primary Key. And type attribute is telling about Java Type. Hibernate will use it to translate Java to SQL data types and vice versa. The generator tag specifies how identity be generated. We use native value, which pick the best strategy in this case Hibernate will use identity startegy. The property tag maps each database column with the JavaBean’s property. From the example, firstName property will map to FIRST_NAME column in the CUSTOMER table.

Hibernate Configuration
To make Hibernate knows how to connect database, the hibernate.cfg.xml file is needed. This file configures the Database Connection and so on. You need to create this file in the src folder by right click on the src folder, choose New → File and name it as hibernate.cfg.xml. Here’s the example of 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>
      <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
      <property name="connection.url">jdbc:hsqldb:mem:localhost</property>
      <property name="connection.username">sa</property>
      <property name="connection.password"></property>
      <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
      <property name="show_sql">true</property>
      <property name="hbm2ddl.auto">create</property>
      <mapping resource="billing/persistence/Customer.hbm.xml" />
   </session-factory>
</hibernate-configuration>

We need to provide the value of the properties so Hibernate can use that value to connect Database and configuring it.
  • connection.driver_class is the property that tells Hibernate which the Database Driver Class it will use. Since we use HSQL DB, the value will be org.hsqldb.jdbcDriver.

  • connection.url is the property to define the connection URL string. We will use our machine as a HSQL DB Server and because of the data in this tutorial doesn’t mean anything to us, so we can use memory database which means all data won’t be persist by using jdbc:hsqldb:mem:localhost.

  • connection.username and connection.password are the properties that define username and password to connect to the database server. We will use the default value, sa for username and blank for password.

  • dialect is the property that tells Hibernate about the database type that we use. The value should be match with the database.

  • show_sql is the property that tells Hibernate to print SQL Command. So we can see what the SQL Command look likes in the console window.

  • hbm2ddl.auto is the property that tell Hibernate to automatically validate or export schema DDL to the database when the SessionFactory is created. The value is create, which means the database schema will be created for us so we won’t bother about creating the database tables for our application.

  • mapping tag tells Hibernate to load the Hibernate Mapping file. Since Customer.hbm.xml is store in billing/persistence directory (the same package as the Customer class) so resource attribute will be billing/persistence/Customer.hbm.xml

The HibernateUtil Class
HibernateUtil class is a helper class that creates SessionFactory object and keep it so SessionFactory will be accessed in the application code through this class. SessionFactory can open a new Session. A Session seems like a delegate class for the JDBC Connection. It represents a single thread unit of work. To create HibernateUtil class, right click on src folder, choose New → Class, name the class as HibernateUtil and keep it in the billing.util package.


package billing.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil
{
   private static final SessionFactory sessionFactory;

   static
   {
      try
      {
         sessionFactory = new Configuration().configure().buildSessionFactory();
      }
      catch (Throwable ex)
      {
         ex.printStackTrace();
         throw new ExceptionInInitializerError(ex);
      }
   }

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

Regarding to this line of code,

sessionFactory = new Configuration().configure().buildSessionFactory();
Hibernate will search for the file name hibernate.cfg.xml in the root of the classpath. If it isn’t found, the exception will be thrown. If everything was fine, the SessionFactory will be created. Then we can access it by the static method getSessionFactory().

Storing and Loading the objects
Finally, it’s time to see how Hibernate works. We will create the Java Application Main class, to monitor how Hibernate stores and loads the objects. Here’s the source code of the Main class.

package billing.demo;

import org.hibernate.Session;
import org.hibernate.Transaction;
import billing.persistence.Customer;
import billing.util.HibernateUtil;

public class Main
{

   @SuppressWarnings("unchecked")
   public static void main (String [] args)
   {
      try
      {
         System.out.println ("Insert data...");
         Session session = HibernateUtil.getSessionFactory().openSession();
         Transaction tx = session.beginTransaction();
         Customer customer = new Customer();
         customer.setFirstName("John");
         customer.setLastName("Doe");
         session.save(customer);
         tx.commit();
         session.close();

         System.out.println ("Query data...");
         Long customerId = customer.getCustomerId();
         session = HibernateUtil.getSessionFactory().openSession();
         customer = (Customer)session.get(Customer.class, customerId);

         System.out.println(customer);
         session.close();

         System.out.println ("Update data...");
         session = HibernateUtil.getSessionFactory().openSession();
         tx = session.beginTransaction();
         customer.setFirstName("Joe");
         customer.setLastName("Ray");
         session.update(customer);
         tx.commit();
         session.close();

         System.out.println ("Query data...");
         session = HibernateUtil.getSessionFactory().openSession();
         customer = (Customer)session.get(Customer.class, customerId);
         System.out.println(customer);
         session.close();
      }
      finally
      {
         HibernateUtil.getSessionFactory().close();
      }
   }
}


  • Session represents a unit of work. In this Main class we call to store and load the objects.

  • Transaction is the API to specify the Transaction Boundaries. The transaction will begin with beginTransaction() method and it will end by commit() or rollback() method. It’s optional.

  • Query is the database query that can be written in Hibernate Query Language (HQL).

Before running the Main class, please check that your project should contains all the files like this,


To run the Main class, right click on Main.java, choose Run As → Java Application. You will see the Console window at the bottom of the screen. If you can’t find the Console window, click on the Window drop down menu → Show View → Console.
After running the Main class, you should see some text like this,


Insert data...
Hibernate: insert into CUSTOMER (CUSTOMER_ID, FIRST_NAME, LAST_NAME) values (null, ?, ?)
Hibernate: call identity()
Query data...
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.FIRST_NAME as FIRST2_0_0_, customer0_.LAST_NAME as LAST3_0_0_ from CUSTOMER customer0_ where customer0_.CUSTOMER_ID=?
[customerId:1], [firstName:John], [lastName:Doe]
Update data...
Hibernate: update CUSTOMER set FIRST_NAME=?, LAST_NAME=? where CUSTOMER_ID=?
Query data...
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.FIRST_NAME as FIRST2_0_0_, customer0_.LAST_NAME as LAST3_0_0_ from CUSTOMER customer0_ where customer0_.CUSTOMER_ID=?
[customerId:1], [firstName:Joe], [lastName:Ray]

Now let’s investigate each unit of work, begin with,
Insert data...
Hibernate: insert into CUSTOMER (CUSTOMER_ID, FIRST_NAME,
LAST_NAME) values (null, ?, ?)
Hibernate: call identity()

First we create a customer, set firstName to John and set lastName to Doe. After calling session.save method, Hibernate generates SQL Insert statement and executes it. You can see that we didn’t set the value for customerId property, since we declare it as an identity property and choose native strategy for it. Hibernate will insert the customerId by calling database identity automatically.
Query data...
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.FIRST_NAME as FIRST2_0_0_, customer0_.LAST_NAME as LAST3_0_0_ from CUSTOMER customer0_ where customer0_.CUSTOMER_ID=?
[customerId:1], [firstName:John], [lastName:Doe]

After inserting John Doe customer, we try to query the data by using customerId. The method session.get, will get the record in CUSTOMER table which have identity value (primary key) as the parameter that we pass to it. You can see the SQL Select statement that Hibernate generates. The last line shows the detail about the Customer object that we just got it from session.get method.
Update data...
Hibernate: update CUSTOMER set FIRST_NAME=?, LAST_NAME=? where CUSTOMER_ID=?

Next we change the firstName to Joe and also change the lastName to Ray. Then we call session.update method. Hibernate generates SQL Update statement and execute it.
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_0_, customer0_.FIRST_NAME as FIRST2_0_0_, customer0_.LAST_NAME as LAST3_0_0_ from CUSTOMER customer0_ where customer0_.CUSTOMER_ID=?
[customerId:1], [firstName:Joe], [lastName:Ray]
The last unit of work, it shows that after changing the properties value and calling session.update method, the data in Customer table have been change. The last line shows firstName and lastName properties have been change to Joe Ray.

Summery
Now you see how Hibernate works, learn how to configure Hibernate, create the mapping file and implement a simple Java Application using Hibernate. Although we don’t use this style of code much in the real world, it is the easiest way to understand Hibernate anyway. If you interested in Hibernate Configuration in more detail, please check the document in Hibernate website. In the next tutorial, you will see a more complex of the Billing System application, how to create association between persistent classes and the mapping file in more detail.