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 SetbillingDetails;
…
public Bill ()
{
setBillingDetails(new HashSet());
}
public SetgetBillingDetails()
{
return billingDetails;
}
public void setBillingDetails(SetbillingDetails)
{
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.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.
<?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>
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.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.
<?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>
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 SetbillingDetails;
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 SetgetBillingDetails()
{
return billingDetails;
}
public void setBillingDetails(SetbillingDetails)
{
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.
No comments:
Post a Comment