web-dev-qa-db-fra.com

Annotation @Transactional. Comment revenir en arrière?

J'ai utilisé cette annotation avec succès pour une classe de Dao. Et la restauration 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 String[] { "HibernateDaoBeans.xml" });
            employeeDao = (IEmployeeDao) context.getBean("employeeDao");
         }

        @Transactional(rollbackFor={Exception.class})
    public void doInsert( Employee newEmp ) throws Exception {
        employeeDao.insertEmployee(newEmp);
        throw new RuntimeException();
    }
}

employéDao 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

   ...
<bean id="employeeDao" class="Hibernate.EmployeeDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
    <tx:annotation-driven transaction-manager="txManager"/>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
   ...



** Oui, j'ai annulé la transaction. Je viens d'ajouter BEAN pour le service ... puis l'annotation @Transactional commence à fonctionner :-) **

<bean id="service" class="main.MyClass">
    <property name="employeeDao" ref="employeeDao" />
</bean>

Merci à tous, la Russie ne vous oubliera pas!

74
Moscow Boy

Il suffit de jeter n'importe quel RuntimeException d'une méthode marquée comme @Transactional.

Par défaut, toutes les transactions d'annulation RuntimeExceptions sont effectuées, contrairement aux exceptions vérifiées. Ceci est un héritage EJB. Vous pouvez le configurer en utilisant les paramètres d'annotation rollbackFor() et noRollbackFor():

@Transactional(rollbackFor=Exception.class)

Cela annulera la transaction après le lancement de any exception.

131
Tomasz Nurkiewicz

ou par programmation

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
60
Stefan K.

Vous pouvez lever une exception non cochée de la méthode que vous souhaitez annuler. Cela sera détecté par spring et votre transaction sera marquée comme annulation uniquement.

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

Le moyen recommandé d'indiquer à l'infrastructure de transaction du cadre Spring que le travail d'une transaction doit être annulé consiste à générer une exception à partir de code en cours d'exécution dans le contexte d'une transaction.

et notez que:

veuillez noter que le code d'infrastructure de transaction du cadre Spring ne marquera, par défaut, qu'une transaction à annuler uniquement dans le cas d'exceptions non vérifiées à l'exécution; c'est-à-dire que lorsque l'exception levée est une instance ou une sous-classe de RuntimeException.

5
Alex Barnes