Question

I'm experiencing a very strange behaviour with Transactions using play-2.2.2 with JPA and Eclipse-Link.

My Controller-Action is annotated with @Transactional like this:

@Transactional
public static Result submitOrder() {
// class does call private Methods which persist some entities (methods not annotated)
//...

Action is calling private methods to persist data (This should happen in the same transaction since no other Transaction is started). During the Methods calls (at random locations) data gets written to db (inserts and updates). Debuging shows that the same (active) transaction is used before and after the write. EntityTransactionImpl:commit is never executed and transaction stays active until request is finished ( watched play.db.jpa.JPA.em().getTransaction() ) How is it possible that the data is written although transaction is still active? It breakes the setRollbackOnly Mechanism since already written data isn't rolled back.

May there be any kind of Timeout that issue these writes. Can you suggest any debug-entry-point to narrow down the problem (where can i start debuging the actual write-operations, if not in EntityTransactionImpl:commit)?

Dependencies in build.sbt

persistence.xml

Was it helpful?

Solution

The above described behaviour seemed very odd at first, but then i read about FlushMode and now it makes sense. The FlushMode of eclipselink as well as hibernate is set to FlushModeType.AUTO FlushModeType.AUTO automatically flushes Entities to the DB when it thinks it's neccessary. This can be because of an readable operation (Query) on a Persited (but not flushed) Entity but it also happened somehow randomly during my observations.

This breaks the rollback-on-failure mechanism, which I thought must be the standard behaviour of @Transactional.

To achive a propper rollback (on failure or if setRollbackOnly() is set), of all persisted but not flushed entities on transcaction commit, you have to explicitly set the FlushMode at the beginning of your Action.

JPA.em().setFlushMode(FlushModeType.COMMIT);

If you're using Eclipselink, you can also set the following property to make it default behaviour:

<property name="eclipselink.persistence-context.flush-mode" value="commit" />

Links which helped me understand:

Eclipselink Context Flushmode

what to use flush mode auto or commit

performance tuning hibernate

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top