program story

@Transactional 주석.

inputbox 2020. 10. 18. 09:22
반응형

@Transactional 주석. 롤백하는 방법?


이 주석을 Dao 클래스에 성공적으로 사용했습니다. 롤백은 테스트를 위해 작동합니다.

하지만 이제는 테스트뿐만 아니라 실제 코드를 롤백해야합니다. 테스트에 사용하기위한 특수 주석이 있습니다. 그러나 비 테스트 코드에 대한 주석은 무엇입니까? 저에게 큰 질문입니다. 나는 이미 하루를 보냈다. 공식 문서가 내 요구를 충족하지 못했습니다.

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>

감사합니다. 러시아는 당신을 잊지 않을 것입니다!


으로 RuntimeException표시된 메소드에서 아무거나 던지십시오 @Transactional.

By default all RuntimeExceptions rollback transaction whereas checked exceptions don't. This is an EJB legacy. You can configure this by using rollbackFor() and noRollbackFor() annotation parameters:

@Transactional(rollbackFor=Exception.class)

This will rollback transaction after throwing any exception.


or programatically

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

You can throw an unchecked exception from the method which you wish to roll back. This will be detected by spring and your transaction will be marked as rollback only.

I'm assuming you're using Spring here. And I assume the annotations you refer to in your tests are the spring test based annotations.

The recommended way to indicate to the Spring Framework's transaction infrastructure that a transaction's work is to be rolled back is to throw an Exception from code that is currently executing in the context of a transaction.

and note that:

please note that the Spring Framework's transaction infrastructure code will, by default, only mark a transaction for rollback in the case of runtime, unchecked exceptions; that is, when the thrown exception is an instance or subclass of RuntimeException.


For me rollbackFor was not enough, so I had to put this and it works as expected:

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

I hope it helps :-)

참고URL : https://stackoverflow.com/questions/7872773/annotation-transactional-how-to-rollback

반응형