Home > database >  How to fix Spring transaction rollback not working while exception
How to fix Spring transaction rollback not working while exception

Time:12-08

I have a service that tries to persist two entites. My expectation is that if one entity is failed to persist, other one should be rolled back and not persisted. But one is persisted while another one is not. Here is my service class

@Service
@Transactional(value = "db1TransactionManager")
public class ServiceImpl {

    @Override
    @Transactional
    public void insertOrUpdate(Entity1 entity1, Entity2 entity2) {
        db1Repository.insert(entity1, Entity1.class);
        db1Repository.insert(entity1, Entity2.class);
    }
}

And here is my repositroy class

@Transactional(value = "db1TransactionManager")
@Repository(value = "db1Repository")
public class Db1RepositoryImpl {

    @PersistenceContext(unitName = "db1")
    private EntityManager em;

    @Override
    public <T> void insert(T entity, Class<T> tClass) {
        em.persist(entity);
//        em.flush();
    }
}

I am intentionally setting entity2 as null to check if rollback works, but entity1 is still persisted. How do i make this transaction atomic?

CodePudding user response:

According to the spring transaction propagation mechanism

The default is PROPAGATION_REQUIRED

We either succeed together or we fail together

So far you appear more like PROPAGATION_NESTED

In other words, the two inserts are not in the same transaction

CodePudding user response:

I am not sure exactly why is this happening but finally solved the problem by removing @Transactional(value = "db1TransactionManager") from repository and placing it on top of the method. Also removed it from class level of service. Still looking for a proper explanation. So here is how it looks now

@Service
public class ServiceImpl {

    @Override
    @Transactional(value = "db1TransactionManager")
    public void insertOrUpdate(Entity1 entity1, Entity2 entity2) {
        db1Repository.insert(entity1, Entity1.class);
        db1Repository.insert(entity1, Entity2.class);
    }
}

and

@Repository(value = "db1Repository")
public class Db1RepositoryImpl {

    @PersistenceContext(unitName = "db1")
    private EntityManager em;

    @Override
    public <T> void insert(T entity, Class<T> tClass) {
        em.persist(entity);
//        em.flush();
    }
}
  • Related