Search code examples
javaspringtransactionsspring-data-jpa

Spring Boot : CrudRepository methods being @Transactional, my service can't be


I have a Spring Boot application and I face a weird issue.

I try to make one of my service method transactional but this doesn't work.

My service looks like this :

@Service("ppService")
public class PlanProgresServiceImpl implements PlanProgresService
{
    @Resource
    private DeploiementDAO deploiementDao;

    ...

    @Override
    @Transactional(rollbackFor = TechnicalErrorException.class)
    public Set<String> deployer(PlanProgresType planProgresType, List<Integer> listIdUo, boolean sharepoint, Campagne campagne)
            throws TechnicalErrorException

        ...

        createDeploiement(deploiement);

        throw new TechnicalErrorException("temporary exception to test the transactional behavior");
    }


    @Override
    public void createDeploiement(Deploiement deploiement)
    {
        deploiementDao.save(deploiement);
    }
}

And here is my DAO :

public interface DeploiementDAO extends CrudRepository<Deploiement, Integer>
{
    List<Deploiement> findByUniteOperationnelle(UniteOperationnelle uo);
}

The thing is that my Deploiement object is always inserted in database (a PostgreSQL one).

I have added the following line in my application.yml logging.level.org.springframework.transaction.interceptor: TRACE

And it gives me this in the console :

2017-05-02 19:38:24.297 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Getting transaction for 
[org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne]
2017-05-02 19:38:24.310 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne]
2017-05-02 19:38:24.312 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne]
2017-05-02 19:38:24.323 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findOne]
2017-05-02 19:38:24.324 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Don't need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findByUniteOperationnelle]: This method isn't transactional.
2017-05-02 19:38:24.449 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
2017-05-02 19:38:24.450 TRACE 7760 --- [io-8080-exec-79] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]

Which means that every methods of SimpleJpaRepository are transactional, that is true when we look at its code :

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

So, how can I solve this ?


Solution

  • Closing this issue. I was a junior back then and I had a bad understanding of how @Transactional worked with Spring.

    TechnicalErrorException needed to be a RuntimeException instead of CheckedException.

    Here is a link that talks about the Transactional Pitfalls: https://codete.com/blog/5-common-spring-transactional-pitfalls