Question

Say I have method somewhere that's annotated @Transactional (thus starts a transaction) and inside do several saveAndFlush(). Maybe I even call some dependency that has a method that starts its own (sub? nested?) transaction by being annotated @Transactional. What gets rolled back if the transaction fails somewhere in between?

some example:

public class ComplexProcess {
    @Inject
    private DAO<SomeEntity> someEntityDao;

    @Inject
    private SomeManagerClass manager;

    @Transactional
    public void doStuff(SomeEntity entity) {
        manager.createAnObjectDependingOnEntity(entity);
        entity = someEntityDao.saveAndFlush(entity); // what if this fails?
        manager.doMoreStuffDependingOnEntity(entity);
    }
}

public class SomeManagerClass {

    @Inject
    private DAO<SomeObject> someObjectDao;

    @Inject
    private DAO<SomeOtherEntity> someOtherEntityDao;

    // what if this fails?
    @Transactional // what if this isn't there?
    public void createAnObjectDependingOnEntity(SomeEntity entity) {
        SomeObject someObject = createSomeObjectDependingOnEntity(entity);
        someObjectDao.saveAndFlush(someObject);
    }

    // what if this fails?
    @Transactional // what if this isn't there?
    public void doMoreStuffDependingOnEntity(SomeEntity entity) {
        SomeOtherEntity someOtherEntity = whatever(entity);
        someOtherEntityDao.safeAndFlush(someOtherEntity);
    }
}

Again: What if say the last step fails, will hibernate still rollback everything that happened before in doStuff()? Because I have a feeling it does not. If this complete rollback is impossible because of saveAndFlush(), will just using save() and waiting for the automatic flush at the end of the transaction help? I've just read that hibernate does some uncontrollable flushes on its own in between even before leaving the @Transactional block?!

Was it helpful?

Solution

  • Flushing should not affect transaction management atl all. When transaction is rolled back, all changes made to the database state (i.e. changes flushed by Hibernate) inside that transaction are rolled back.

  • Default propagation policy for @Transactional is PROPAGATION_REQUIRED. It means that you can safely invoke @Transactional methods from other @Transactional methods, and they'll use the same transaction created by the top level transaction method. It's not so if you provide different propagation settings explicitly.

So, it means that any failure that happens during execution of the top level @Transactional method (i.e. any exception thrown from that method) should cause rollback, and all changes should be rolled back in this case.

If you observe different behavior, perhaps something is misconfigured (for example, the top level @Transactional doesn't take effect for some reason). Try to reproduce this behavior in tests.

OTHER TIPS

With your code all the changes Hibernate made should be rolled back, if somewhere it is decided to roll back the current transaction. Of course, only if everything is correctly configured.

Some common configuration problems are: Your persistence.xml should define a JTA persistence unit (instead of a RESOURCE_LOCAL) and your database/tables should support transactions (e.g MySQL tables should be with the InnoDb search engine).

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