복붙노트

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

SPRING

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

고마워, 러시아는 너를 잊지 않을 것이다!

해결법

  1. ==============================

    1.@Transactional로 표시된 메소드에서 RuntimeException을 던지십시오.

    @Transactional로 표시된 메소드에서 RuntimeException을 던지십시오.

    기본적으로 모든 RuntimeExceptions 롤백 트랜잭션은 확인 된 예외가 아니라 트랜잭션을 롤백합니다. 이것은 EJB 레거시입니다. rollbackFor () 및 noRollbackFor () 주석 매개 변수를 사용하여이를 구성 할 수 있습니다.

    @Transactional(rollbackFor=Exception.class)
    

    이것은 예외를 던진 후에 트랜잭션을 롤백합니다.

  2. ==============================

    2.또는 프로그래밍 방식으로

    또는 프로그래밍 방식으로

    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    
  3. ==============================

    3.롤백하려는 메소드에서 검사되지 않은 예외를 throw 할 수 있습니다. 이것은 봄까지 감지되며 거래는 롤백으로 만 표시됩니다.

    롤백하려는 메소드에서 검사되지 않은 예외를 throw 할 수 있습니다. 이것은 봄까지 감지되며 거래는 롤백으로 만 표시됩니다.

    여기 스프링을 사용하고 있다고 가정합니다. 그리고 테스트에서 참조하는 주석은 스프링 테스트 기반 주석입니다.

    참고 :

  4. ==============================

    4.API에 Rollback () 메소드를 만들려면 방법이있을 수 있습니다. 새 메소드 ()를 만듭니다.

    API에 Rollback () 메소드를 만들려면 방법이있을 수 있습니다. 새 메소드 ()를 만듭니다.

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

    "rollbackOnly로 표시된 트랜잭션"롤백 예외를 알아야 할 수도 있습니다.

  5. ==============================

    5.나를 위해 rollbackFor 충분하지 않아서, 나는 이것을 넣어야만했고 예상대로 작동합니다 :

    나를 위해 rollbackFor 충분하지 않아서, 나는 이것을 넣어야만했고 예상대로 작동합니다 :

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

    나는 그것이 도움이되기를 바란다 :-)

  6. from https://stackoverflow.com/questions/7872773/annotation-transactional-how-to-rollback by cc-by-sa and MIT license