Аннотация @Transactional. Как откатиться? - PullRequest
69 голосов
/ 24 октября 2011

Я успешно использовал эту аннотацию для класса Дао.И откат работает на тесты.

Но теперь мне нужно откатить реальный код, а не только тесты.Есть специальные аннотации для использования в тестах.Но какие аннотации для не тестового кода?Это большой вопрос для меня.Я провел день для этого уже.Официальная документация не соответствовала моим потребностям.

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();
    }
}

employeeDao равен

@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);
    }
}

А вот тест, для которого аннотации работают хорошо:

@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>
   ...



** ДА, я откатил транзакцию.Я просто добавил BEAN для сервиса ... и тогда аннотация @Transactional начинает работать :-) **

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

Спасибо всем, Россия вас не забудет!

Ответы [ 4 ]

126 голосов
/ 24 октября 2011

Просто бросьте любой RuntimeException из метода, помеченного как @Transactional.

По умолчанию все транзакции отката RuntimeException s, тогда как отмеченные исключения - нет. Это наследие EJB. Это можно настроить с помощью параметров аннотаций rollbackFor() и noRollbackFor():

@Transactional(rollbackFor=Exception.class)

Это откат транзакции после выброса любого исключения.

58 голосов
/ 21 января 2016

или программно

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
4 голосов
/ 24 октября 2011

Вы можете выбросить непроверенное исключение из метода, который вы хотите откатить.Это будет обнаружено весной, и ваша транзакция будет помечена только как откат.

Я предполагаю, что вы используете Spring здесь.И я предполагаю, что аннотации, на которые вы ссылаетесь в своих тестах, являются аннотациями на основе весенних тестов.

Рекомендованный способ указать инфраструктуре транзакций Spring Framework на то, что работа транзакции должна быть откачена, - это выброситьИсключение из кода, который в данный момент выполняется в контексте транзакции.

и обратите внимание, что:

обратите внимание, что код инфраструктуры транзакций Spring Framework по умолчанию будет, отмечать транзакцию для отката только в случае выполнения, непроверенных исключений;то есть, когда выброшенное исключение является экземпляром или подклассом RuntimeException.

0 голосов
/ 13 декабря 2017

Для меня отката для меня было мало, поэтому пришлось поставить вот это и все работает как положено:

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

Надеюсь, это поможет: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...