programing

예외 없이 트랜잭션 롤백을 수행하시겠습니까?

instargram 2023. 7. 26. 21:35
반응형

예외 없이 트랜잭션 롤백을 수행하시겠습니까?

여러 가지 작업을 수행하는 방법이 있습니다. 그 중에서도 여러 개의 삽입과 업데이트를 수행합니다.

다음과 같이 선언됩니다.

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public int saveAll() {
 //do stuff;
}

그것은 정확히 원래대로 작동하고 저는 문제가 없습니다.하지만 예외가 없음에도 불구하고 롤백을 강제로 실행하고 싶을 때가 있습니다.지금은 조건이 맞으면 무조건 예외를 강요하고 있지만, 보기 흉하고 마음에 안 들어요.

어떻게든 롤백을 적극적으로 호출할 수 있습니까?

예외적으로...저도 할 수 있을 것 같아요.

스링트랜션서다사용다니합음을에잭프다사를 합니다.TransactionStatus.setRollbackOnly().

여기서 문제는 당신이 사용하고 있다는 것입니다.@Transactional사용자의 트랜잭션을 구분합니다.이것은 비침습적이라는 이점이 있지만, 트랜잭션 컨텍스트와 수동으로 상호 작용하려면 할 수 없다는 것을 의미하기도 합니다.

트랜잭션 상태를 엄격하게 제어하려면 선언적 주석 대신 프로그래밍 방식의 트랜잭션을 사용해야 합니다.즉, Spring's Transaction을 사용합니다.템플릿을 작성하거나 플랫폼 트랜잭션 관리자를 직접 사용합니다.스프링 참조 매뉴얼의 섹션 9.6을 참조하십시오.

와 함께TransactionTemplate은 다을구현콜개제공다니합체를 합니다.TransactionCallback 이 는 그고이콜코액수할있다습니세스드는리백의▁▁to▁in에 접속할 수 .TransactionStatus물건들.

다 좋지 않습니다@Transactional하지만 당신은 당신의 tx 상태를 더 가까이 통제할 수 있습니다.

이것은 나에게 도움이 됩니다.

TransactionInterceptor.currentTransactionStatus().setRollbackOnly();

우리는 EJB를 사용하지 않고, 단순한 Spring과 AOP 접근 방식을 선택했습니다.새로운 을 구현했습니다.@TransactionalWithRollback그리고 AOP를 사용하여 주석이 달린 방법을 "주변" 조언으로 포장했습니다.하는 것은 다음과 같습니다.TransactionTemplate할 때 하지만, 에 주석을 달 수 있습니다.@TransactionalWithRollback우리가 흔히 쓰는 것처럼@Transactional 간단해 .메인 코드는 깔끔하고 간단해 보입니다.

//
// Service class - looks nice
//
class MyServiceImpl implements MyService {
    @TransactionalWithRollback
    public int serviceMethod {
        // DO "read only" WORK
    }
}

//
// Annotation definition
//
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface TransactionalWithRollback {
}

//
// the around advice implementation
//
public class TransactionalWithRollbackInterceptor {
    private TransactionTemplate txTemplate;
    @Autowired private void setTransactionManager(PlatformTransactionManager txMan) {
        txTemplate = new TransactionTemplate(txMan);
    }

    public Object doInTransactionWithRollback(final ProceedingJoinPoint pjp) throws Throwable {
        return txTemplate.execute(new TransactionCallback<Object>() {
            @Override public Object doInTransaction(TransactionStatus status) {
                status.setRollbackOnly();
                try {
                    return pjp.proceed();
                } catch(RuntimeException e) {
                    throw e;
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
}

//
// snippet from applicationContext.xml:
//
<bean id="txWithRollbackInterceptor" class="net.gmc.planner.aop.TransactionalWithRollbackInterceptor" />

<aop:config>
    <aop:aspect id="txWithRollbackAspect" ref="txWithRollbackInterceptor">
        <aop:pointcut 
            id="servicesWithTxWithRollbackAnnotation" 
            expression="execution( * org.projectx..*.*(..) ) and @annotation(org.projectx.aop.TransactionalWithRollback)"/>
        <aop:around method="doInTransactionWithRollback" pointcut-ref="servicesWithTxWithRollbackAnnotation"/>
    </aop:aspect>
</aop:config>

setRollbackOnly()에서.SessionContextEJB에 있는 경우.

주사를 놓을 수 .SessionContext 예:

public MyClass {
    @Resource
    private SessionContext sessionContext;

    @Transactional(propagation = Propagation.REQUIRED, 
                   isolation = Isolation.DEFAULT, 
                   readOnly = false)
    public int saveAll(){
        //do stuff;
        if(oops == true) {
             sessionContext.setRollbackOnly();
             return;
        }
    }

setRollbackOnly() 다멤다 ▁is의▁of▁member.EJBContext.SessionContext 확된장EJBContexthttp://java.sun.com/j2ee/1.4/docs/api/javax/ejb/SessionContext.html 세션 EJB에서만 사용할 수 있습니다.

@Resource는 표준 Java EE 주석이므로 Eclipse에서 설정을 확인해야 합니다.다음은 다음을 사용하여 세션 컨텍스트를 주입하는 방법의 예입니다.@Resource.

EJB와 함께 작업하지 않을 수도 있기 때문에 이클립스가 발견하지 못하는 이유를 설명하는 것은 아마도 당신의 해결책이 아닐 것입니다.@Resource.

그런 경우에는 트랜잭션과 직접 상호 작용해야 합니다. 트랜잭션 템플릿을 참조하십시오.

당신은 봄에 거래 관리자를 투입해야 합니다.그러면 롤백 방법을 호출하면 됩니다.

다음과 같은 주석이 달린 서비스 방법이 있습니다.@Transactional유효성 검사에 실패하고 현재 작업 단위에 이미 연결된 엔티티가 있는 경우 사용sessionFactory.getCurrentSession().evict(entity)데이터베이스에 기록된 내용이 없는지 확인합니다.그래야 제가 예외를 둘 필요가 없습니다.

지금은 적당한 조건에 부딪히면 무조건 예외를 강요하고 있지만, 보기 흉하고 마음에 들지 않습니다.

왜 못생겼어요?저는 그렇지 않다고 주장할 것입니다.당신은 당신의 것을 가지고 있습니다.@Transactional당신의 공개적인 방법으로.rollbackFor이와 같은 속성:

@Transactional(rollbackFor = Exception.class)
public void myMethod() throws IllegalStateException {

그런 다음 메소드가 남쪽으로 이동하면 표준 Java 예외가 발생합니다. 아마도 다음과 같습니다.

throw new IllegalStateException("XXX");

이것은 아름답습니다. 기존의 표준 Java 예외를 1-라이너만 사용하여 사용하면 프레임워크가 롤백을 수행합니다. 이것으로 끝입니다.

예외를 적용하고 프레임워크를 설계된 대로 사용합니다. 그렇지 않으면 선언적 트랜잭션 관리를 사용하지 말고 위의 직원 조언을 따르십시오.단순하게 받아들여라.

언급URL : https://stackoverflow.com/questions/832375/force-a-transactional-rollback-without-encountering-an-exception

반응형