views:

27

answers:

1

Hello,

The following code throws an exception when invoking "em.refresh(p)":

1: EntityManager em = emf.createEntityManager();
2: em.getTransaction().begin();
3:
4: Product p = new Product("J&D", 35.0,"Whisky");
5: em.persist(p);
6:
7: em.refresh(p);
8: em.getTransaction().commit();
9: em.close();

When debugging the code, we see that Hibernate didn't write the record into the DB at line 6. He does is like foreseen - when it's required, not earlier.

At line 7, we get the following exception: Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.HibernateException: this instance does not yet exist as a row in the database

When we force Hibernate to flush the record into the DB at line 6, the INSERT is executed and no error occurs. We can do this by executing a select or just force the flush (with all consequences):

6 : em.createQuery("select p from Product p").getResultList();
6 : em.flush();

My question: should the method "refresh" not force Hibernate to write the record into the DB, as does the select or the flush statement wehn placesd before? (Might this be a bug?).

Thanks in advance for your answers.

Pierre

+1  A: 

should the method "refresh" not force Hibernate to write the record into the DB, as does the select or the flush statement when placed before? (Might this be a bug?).

No, refresh should not flush changes since the whole point of refresh is to revert any non-flushed changes made in the current transaction. This is maybe better explained in the JPA wiki book than in the specification:

The EntityManager#refresh(Object) operation is used to refresh an object's state from the database. This will revert any non-flushed changes made in the current transaction to the object, and refresh its state to what is currently defined on the database. If a flush has occurred, it will refresh to what was flushed. Refresh must be called on a managed object, so you may first need to find the object with the active EntityManager if you have a non-managed instance.

So you should indeed flush after the persist if you want your code to work.

That being said, I don't see the point of doing a refresh just after a persist (assuming you flushed the changes), there is just nothing to refresh here. Maybe it's just a simplified example though.

References

  • JPA 2.0 specification
    • 3.2.5 Refreshing an Entity Instance
  • JPA Wiki book
Pascal Thivent