Hibernate: continuing the path of discovery

This is a continuation of my previous post. This post investigates the various properties available on the class element available in the persistent class hbm.xml file.


Let’s try and scratch beneath the surface. I continue to use the previous post example of Person object. Run the application and observe the hibernate log. The output generated in the following format:

Hibernate: insert into PERSON (firstName, lastName, dob, id)
           values (?, ?, ?, ?)

Let’s try some variation here.

Configuration cfg = new Configuration();
cfg.configure();
SessionFactory sessFactory = cfg.buildSessionFactory();
//Inserting a row in MySQL database using Hibernate.
try {
	Session session = sessFactory.openSession();
	Person p = new Person();
	p.setId("11010");
	p.setFirstName("Billy");
	p.setLastName("Kid");
	p.setDob(new java.util.Date());

	Transaction tx = session.beginTransaction();
	session.save(p);
	tx.commit();
	session.close();
	System.out.println("Completed Row INSERT.");
} catch(Exception e) {
	e.printStackTrace();
}

//Updating a row in MySQL database using Hibernate.
try {
	Session session = sessFactory.openSession();
	Transaction tx = session.beginTransaction();
	String query = "FROM Person AS p WHERE p.firstName = 'Billy'";
	System.out.println("Querying the INSERTED ROW for the first" + 
		" time.");
	Query q = session.createQuery(query);
	List l = q.list();
	for (Object object : l) {
		Person p = (Person)object;
		System.out.println("Retrieved INSERTED ROW");
		p.setFirstName("James");
		session.update(p);
		System.out.println("UPDATED ROW.");
	}
	query = "FROM Person AS p WHERE p.firstName = 'James'";
	System.out.println("Querying the INSERTED ROW");
	q = session.createQuery(query);
	l = q.list();
	for (Object object : l) {
		Person p = (Person)object;
		System.out.println("Retrieved UPDATED ROW");
	}
	tx.commit();
} catch (Exception ex) {
	ex.printStackTrace();
}

Let’s see what we have tried here. We are inserting a row, retrieving the row, updating the row. During each operation, the changes are being persisted in the database. The hibernate log output is as follows:

 

Hibernate: insert into PERSON (firstName, lastName, dob, id)
           values (?, ?, ?, ?)
           Completed Row INSERT.
           Querying the INSERTED ROW for the first time.
Hibernate: select person0_.id as id0_, person0_.firstName as 
	       firstName0_,......
           from PERSON person0_ where person0_.firstName='Billy'
           Retrieved INSERTED ROW
           UPDATED ROW.
           Querying the INSERTED ROW
Hibernate: update PERSON set firstName=?, lastName=?, dob=? where id=?
Hibernate: select person0_.id as id0_, person0_.firstName as firstName0_,
           person0_.lastName as lastName0_, person0_.dob as dob0_
           from PERSON person0_ where person0_.firstName='James'

Nothing special occured here except one small thing. The UPDATE was triggered much after the session.update() call. Hibernate reduces network chattiness by controlling database interactions. The UPDATE was triggered just before the row was being retrieved by the subsequent query.

I had updated only the first name field but the UPDATE statement updated all the fields on the Person object. This problem cane be resolved via a small change in the Person.hbm.xml. Add the dynamic-update and dynamic-insert attributes in the Class element of the Person.hbm.xml.

<class name="Person" table="PERSON" dynamic-update="true" 
	dynamic-insert="true">

Comment out the line p.setDob(new java.util.Date()) and run the code provided above.

The Hibernate output is as below:

Hibernate: insert into PERSON (firstName, lastName, id) values (?, ?, ?)
           Completed Row INSERT.
           Querying the INSERTED ROW for the first time.
Hibernate: select person0_.id as id0_, person0_.firstName as firstName0_,
           person0_.lastName as lastName0_, person0_.dob as dob0_
           from PERSON person0_ where person0_.firstName='Billy'
           Retrieved INSERTED ROW
           UPDATED ROW.
           Querying the INSERTED ROW
Hibernate: update PERSON set firstName=? where id=?
Hibernate: select person0_.id as id0_, person0_.firstName as firstName0_,
           person0_.lastName as lastName0_, person0_.dob as dob0_
           from PERSON person0_ where person0_.firstName='James'
           Retrieved UPDATED ROW

Refer the highlighted sections of the output. The INSERT statement does not have the dob field and the UPDATE statement is only setting the firstname field. Just some of the features that helps the developer extract better performance from Hibernate.

Now that we are exploring the features available in the class element definition, let’s look at one more feature. Here’s the sample program:

		Configuration cfg = new Configuration();
		cfg.configure();
		SessionFactory sessFactory = cfg.buildSessionFactory();
		//Inserting a row in MySQL database using Hibernate.
		Person p = null;
		try {
			Session session = sessFactory.openSession();
			Transaction tx = session.beginTransaction();
			p = new Person();
			p.setId("99999");
			p.setFirstName("Billy");
			p.setLastName("Kid");
			p.setDob(new java.util.Date());
			session.save(p);
			System.out.println("Completed Row INSERT.");

			p.setLastName("Idol");
			System.out.println("Before Row UPDATE.");
			session.update(p);
			tx.commit();
			session.close();
			System.out.println("Completed Row UPDATE.");
		} catch(Exception e) {
			e.printStackTrace();
		}

The output generated is as follows:

           Completed Row INSERT.
           Before Row UPDATE.
Hibernate: insert into PERSON (firstName, lastName, dob, id)
           values (?, ?, ?, ?)
Hibernate: update PERSON set lastName=? where id=?
           Completed Row UPDATE.

Add the following attribute in the class element definition for Person.

select-before-update="true"

Now run the sample program. The output generated as follows:

           Completed Row INSERT.
           Before Row UPDATE.
Hibernate: insert into PERSON (firstName, lastName, dob, id)
           values (?, ?, ?, ?)
Hibernate: update PERSON set lastName=? where id=?
           Completed Row UPDATE.

No difference from the earlier output. Now let’s tweak the sample program a little and observe the output.

 		Configuration cfg = new Configuration();
		cfg.configure();
		SessionFactory sessFactory = cfg.buildSessionFactory();
		//Inserting a row in MySQL database using Hibernate.
		Person p = null;
		try {
			Session session = sessFactory.openSession();
			Transaction tx = session.beginTransaction();
			p = new Person();
			p.setId("99999");
			p.setFirstName("Billy");
			p.setLastName("Kid");
			p.setDob(new java.util.Date());
			session.save(p);
			System.out.println("Completed Row INSERT.");
			tx.commit();
			session.close();
			System.out.println("Row INSERT COMMITTED.");

			session = sessFactory.openSession();
			tx = session.beginTransaction();
			p.setLastName("Idol");
			System.out.println("Before Row UPDATE.");
			session.update(p);
			tx.commit();
			session.close();
			System.out.println("Completed Row UPDATE.");

		} catch(Exception e) {
			e.printStackTrace();
		}
           Completed Row INSERT.
Hibernate: insert into PERSON (firstName, lastName, dob, id) 
	       values (?, ?, ?, ?)
           Row INSERT COMMITTED.
           Before Row UPDATE.
Hibernate: select person_.id, person_.firstName as firstName0_,
           person_.lastName as lastName0_, person_.dob as dob0_
           from PERSON person_ where person_.id=?
Hibernate: update PERSON set lastName=? where id=?
           Completed Row UPDATE.

We notice a slight difference in the output. Hibernate has done a SELECT before the UPDATE. Let’s check the out when the property select-before-update is turned off.

select-before-update="false"

The output now is:

           Completed Row INSERT.
Hibernate: insert into PERSON (firstName, lastName, dob, id)
           values (?, ?, ?, ?)
           Row INSERT COMMITTED.
           Before Row UPDATE.
Hibernate: update PERSON set firstName=?, lastName=?, dob=?
           where id=?
           Completed Row UPDATE.

For the same sample program code hibernate has not done a SELECT before updating the row. If the Person data had changed in the interval between the session closure and opening, that information would not have been available to the program. Just a small gotcha to keep one’s eyes peeled.




Moving along noticed an innocuous attribute called mutable. Initially I left the mutable attribute to its default value of “true”. Here’s the sample program:

	Configuration cfg = new Configuration();
	cfg.configure();
	SessionFactory sessFactory = cfg.buildSessionFactory();
	try {
		Session session = sessFactory.openSession();

		Person p = new Person();
		p.setId("218");
		p.setFirstName("T1om");
		p.setLastName("Jones");
		p.setDob(new java.util.Date());

		Transaction tx = session.beginTransaction();
		session.save(p);
		tx.commit();

		session = sessFactory.openSession();
		Query q = session.createQuery("FROM Person as p " + 
			"WHERE p.id = 216");
		List l = q.list();

		for (Object object : l) {
			p = (Person)object;

		}
		tx = session.beginTransaction();
		p.setFirstName("Dude");
		session.update(p);
		tx.commit();

	} catch(Exception e) {
		e.printStackTrace();
	}

Here’s the output generated:

Hibernate: insert into PERSON (firstName, lastName, dob, id) 
	       values (?, ?, ?, ?)
Hibernate: select person0_.id as id0_, person0_.firstName as firstName0_,
           person0_.lastName as lastName0_, person0_.dob as dob0_
           from PERSON person0_ where person0_.id=218
Hibernate: update PERSON set firstName=? where id=?

Now I changed the attribute to mutable=”false”. The ouput generated was:

Hibernate: insert into PERSON (firstName, lastName, dob, id) 
	       values (?, ?, ?, ?)
Hibernate: select person0_.id as id0_, person0_.firstName as firstName0_,
           person0_.lastName as lastName0_, person0_.dob as dob0_
           from PERSON person0_ where person0_.id=218

The update did not happen. In case you intend to make a table INSERT only, you would find this attribute extremely useful.

That’s it from my desk for now. Next I intend to cover relationships using hibernate.



Published by Vinay Rajadhyaksha

Vinay Rajadhyaksha a.k.a Mr President

4 thoughts on “Hibernate: continuing the path of discovery

  1. Hello Mr President

    I am using struts1.3 and hibernate3.0 in combination. Usually when we run our application we see the queries that are fired by hibernate but in my case I am able to see the select query fired but I am not abe to see the session.update query fired. Even my database is not updated. there are no errors or exceptions please help me

    Thanks in advance.

    Regards
    Soniya

  2. Soniya,

    Your inputs are insufficient. Could you atleast send me your code. I hope you have invoked transaction.commit(). Thats a quick suggestion from me.

Leave a comment