Annotation @Transactional. Comment annuler?

J’ai utilisé cette annotation avec succès pour une classe Dao. Et le retour en arrière fonctionne pour les tests.

Mais maintenant, je dois annuler le code réel, pas seulement les tests. Il existe des annotations spéciales à utiliser dans les tests. Mais quelles annotations sont pour le code non-test? C’est une grande question pour moi. J’ai déjà passé une journée pour ça. La documentation officielle ne répondait pas à mes besoins.

class MyClass { // this does not make rollback! And record appears in DB. EmployeeDaoInterface employeeDao; public MyClass() { ApplicationContext context = new ClassPathXmlApplicationContext( new Ssortingng[] { "HibernateDaoBeans.xml" }); employeeDao = (IEmployeeDao) context.getBean("employeeDao"); } @Transactional(rollbackFor={Exception.class}) public void doInsert( Employee newEmp ) throws Exception { employeeDao.insertEmployee(newEmp); throw new RuntimeException(); } } 

employeeDao est

 @Transactional public class EmployeeDao implements IEmployeeDao { private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public void insertEmployee(Employee emp) { sessionFactory.getCurrentSession().save(emp); } } 

Et voici un test pour lequel les annotations fonctionnent bien:

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "/HibernateDaoBeans.xml" }) @TransactionConfiguration(transactionManager = "txManager", defaultRollback = true) @Transactional public class EmployeeDaoTest { @Autowired EmployeeDaoInterface empDao; @Test public void insert_record() { ... assertTrue(empDao.insertEmployee(newEmp)); } 

HibernateDaoBeans.xml

  ...        ... 



** OUI, j’ai annulé la transaction. Je viens d’append BEAN pour le service … et ensuite l’annotation @Transactional commence à fonctionner 🙂 **

    

Merci à tous, la Russie ne vous oubliera pas!

Il suffit de lancer une RuntimeException partir d’une méthode marquée comme @Transactional .

Par défaut, toutes les transactions de restauration de RuntimeException , contrairement aux exceptions cochées. C’est un inheritance d’EJB. Vous pouvez le configurer à l’aide des parameters d’annotation rollbackFor() et noRollbackFor() :

 @Transactional(rollbackFor=Exception.class) 

Cela annulera la transaction après avoir lancé une exception.

ou par programmation

 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 

Vous pouvez lancer une exception non vérifiée à partir de la méthode que vous souhaitez annuler. Cela sera détecté au spring et votre transaction sera marquée comme une restauration uniquement.

Je suppose que vous utilisez le spring ici. Et je suppose que les annotations auxquelles vous faites référence dans vos tests sont les annotations basées sur les tests printaniers.

La méthode recommandée pour indiquer à l’infrastructure de transaction de Spring Framework que le travail d’une transaction doit être annulé consiste à lancer une exception à partir du code en cours d’exécution dans le contexte d’une transaction.

et notez que:

Veuillez noter que le code d’infrastructure de transaction de Spring Framework ne marquera, par défaut, qu’une transaction pour une annulation dans le cas d’exceptions, non vérifiées. c’est-à-dire lorsque l’exception renvoyée est une instance ou une sous-classe de RuntimeException.

Si vous souhaitez créer une méthode Rollback () dans votre API, il pourrait y avoir un moyen. Créez une nouvelle méthode ().

 @Component public class MyDBApiImpl implements MyDBApi{ @Autowired private DummyExceptionLauncher dummyExceptionLauncher; @Override @Transactional(propagation=Propagation.MANDATORY) public void rollback(){ try{ dummyExceptionLauncher.throwException(); }catch(RuntimeException ex){ log.debug("Transaction deliberately aborted"); } } } 

 @Component public class DummyExceptionLauncherImpl implements DummyExceptionLauncher{ @Override @Transactional(propagation=Propagation.MANDATORY) public void throwException(){ throw new RuntimeException("Exception deliberated thrown to abort exception"); } } 

Attention, vous devrez peut-être intercepter des exceptions de restauration “Transaction marquée comme rollbackOnly”.

Pour moi, rollbackFor n’était pas suffisant, alors j’ai dû mettre ça et ça fonctionne comme prévu:

 @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class) 

J’espère que ça aide 🙂