1

I'm not sure if this is correct, but I need that after a transaction is rollbacked, my object returns the its initial state. I created a junit test and it's failing.

try {
    entityManager.getTransaction().begin();
    entityManager.persist(itemBec);
    //            throw new Exception("teste");
    //            throw new EJBTransactionRolledbackException("teste");
    //            throw new ConstraintViolationException("teste", null, null);
    throw new RuntimeException("teste");
} catch (Exception e) {
    entityManager.getTransaction().rollback();
} finally {
    if (entityManager.getTransaction().isActive()) {
        entityManager.getTransaction().commit();
    }
}
entityManager.close();
factory.close();
Assert.assertNull(itemBec.getId());

Am I wrong to assume that the object must return do its initial state?

Thanks.

1 Answers1

3

Am I wrong to assume that the object must return do its initial state?

Hibernate won't rollback object state. It's best to never reuse objects across transactions, so that such problem does not appear.

From this answer quoting the spec (emphasis is mine):

Transaction Rollback

For both transaction-scoped and extended persistence contexts, transaction rollback causes all pre-existing managed instances and removed instances [31] to become detached. The instances’ state will be the state of the instances at the point at which the transaction was rolled back. Transaction rollback typically causes the persistence context to be in an inconsistent state at the point of rollback. In particular, the state of version attributes and generated state (e.g., generated primary keys) may be inconsistent. Instances that were formerly managed by the persistence context (including new instances that were made persistent in that transaction) may therefore not be reusable in the same manner as other detached objects—for example, they may fail when passed to the merge operation. [32]

This is why I believe it's better to no reuse entites across transactions: while it might work as long as transactions commit sucessfully, if transactions fail, things become more complicated. Usually, there's no compelling reasons to reuse entites across transactions anyway.

Community
  • 1
  • 1
ewernli
  • 38,045
  • 5
  • 92
  • 123
  • 1
    +1 Usually EntityManager scope is bounded to transaction one. Maybe "never" is a bit strong word however. – Gab May 23 '13 at 14:35
  • 1
    @Gab Hm. Maybe "never" is a bit too strong, but I think it's really a best practice, unless you know the in and out of JPA! (I added one of the snippet of the spec as justification) – ewernli May 23 '13 at 14:55
  • Thanks a lot for the precision. I had never used a non transaction-scoped EntityManager but i thought it could be useful to reuse same entities to try to recover from error when this last is not due to the entities state (in case of XA transaction when another resource manipulated in same transaction fails for example). – Gab May 23 '13 at 15:46
  • Thanks for all the answers. – liviasilvasantos May 24 '13 at 20:50