Home > Java > Hibernate hard facts part 1

Hibernate hard facts part 1

Hibernate LogoHibernate is a widely-used ORM framework. Many organizations use it across their projects in order to manage their data access tier. Yet, many developers working on Hibernate don’t fully understand the full measure of its features. In this serie of articles, I will try to dispel some common misunderstandings regarding Hibernate.

Updating a persistent object

A widely made mistake using Hibernate is to call the update() method on an already persistent object :

session.getTransaction().begin();

Person person = (Person) session.load(Person.class, 1L);

person.setLastName("FooBar");

session.update(person);

session.getTransaction().commit();

This will get you the following Hibernate outputs :

Hibernate: select person0_.id as id0_0_,
    person0_.birthDate as birthDate0_0_,
    person0_.FIRST_NAME as FIRST3_0_0_,
    person0_.LAST_NAME as LAST4_0_0_ from Person person0_ where person0_.id=?
Hibernate: update Person set birthDate=?, FIRST_NAME=?, LAST_NAME=? where id=?

Now remove the line numbered 7. You get exactly the same output! If you check the database, the result will be the same: calling update() does nothing since the object is already persistent. If you are in debug mode, you can even check that the output’s update line is called when commiting the transaction in both cases.

You will find proof of this assertion here.

email
Send to Kindle
  1. joonas
    December 14th, 2009 at 17:34 | #1

    Should be noted that much relies on your current flush mode (Session#getFlushMode) which many might not know of.

    By default flush mode ought to be FlushMode#AUTO, which means that changes to tracked entities will be flushed at latest before commit, but also before any dependant queries. Dependant queries as in queries to which your changes can cause different results — in the above example any queries related to Persons and entities related to Person.

    MANUAL (previously NEVER) allows you to delay changes until you call Session#flush().

    COMMIT delays (don’t know if there are exceptions to this, at least javadoc doesn’t specify those) until, well the transaction commit.

    ALWAYS delays until every query, or commit.

    You can control change tracking through for example Session#setReadOnly(Object, boolean), Query#setReadOnly(boolean), Criteria#setReadOnly(boolean).

    Spring @Transaction’s readOnly applies to Hibernate through the sessions flush mode (if you use HibernateTransactionManager).

  2. btilford
    March 4th, 2010 at 04:16 | #2

    What happens in the (probably most common) scenario where the object is retrieved during an http request and updated in another http request? e.g. When you update you are using a different Session.

  3. March 4th, 2010 at 20:10 | #3

    Is the Session you’re refering to an HTTP session or an Hibernate Session? Could you be more specific in your question? What happens is a little vague.

  4. Disnarda
    March 11th, 2010 at 22:25 | #4

    @Nicolas Frankel
    I think he is refering to another Hibernate Session, when the object is in deatached state.

  5. March 11th, 2010 at 22:30 | #5

    @Disnarda
    Thanks, “what happens” is still a little vague but now I know the context…

  6. William Antônio Siqueira
    June 8th, 2011 at 14:52 | #6

    Hi Nicolas,

    Great article! Thanks for writing this!

    Note: Seems the Hibernate page link is broken.

    []‘s

  1. June 27th, 2009 at 00:36 | #1
  2. December 26th, 2009 at 01:49 | #2
  3. December 26th, 2009 at 01:50 | #3