Spring Boot - @Transactional ne fonctionne pas
Bonjour,
J'ai une application Spring Boot on ne peut plus classique.
J'ai une classe annotée @Service dans laquelle j'ai une méthode annotée @Transactional. Le but étant que si ça pète, peut-importe le type d'exception jetée, un rollback soit fait.
Malheureusement, aucun rollback n'est fait.
Je vous mets un peu de code :
Le service :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| @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);
}
} |
Le DAO :
Code:
1 2 3 4
| public interface DeploiementDAO extends CrudRepository<Deploiement, Integer>
{
List<Deploiement> findByUniteOperationnelle(UniteOperationnelle uo);
} |
Comme vous pouvez le constater, j'ai forcé une exception pour tester le comportement transactionnel de la méthode. Mais malgré tout, la ligne est toujours inséré en base de données (une BDD PostgreSQL).
J'ai décidé d'afficher un log des transactions en ajoutant la ligne suivante à mon fichier application.yml :
Citation:
logging.level.org.springframework.transaction.interceptor: TRACE
Et cela me donne la trace suivante :
Code:
1 2
| 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] |
Je trouve ça étrange, juste avant l'exception, on m'indique que la sauvegarde du déploiement est commité ?
En regardant le code de SimpleJpaRepository, je constate que la méthode save() est transactionnelle. Ce qui explique les deux lignes ci-dessus :
Code:
1 2 3 4 5 6 7 8 9 10
| @Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
} |
Du coup, comment puis-je rendre ma méthode transactionnelle ?
Ce que j'ai essayé :
- Ajouter @EnableTransactionManagement à une classe @Configuration
- Lancer une RuntimeException au lieu d'une "checked exception"
- Mettre "Exception.class" au lieu de "TechnicalErrorException.class" dans le rollbackFor de @Transactional