2012-01-23 2 views
6

Grails 애플리케이션에서 서비스 메소드의 기본 동작은 트랜잭션 방식이며 트랜잭션이 체크되지 않은 예외가 발생하면 자동으로 롤백된다는 것입니다. 그러나 Groovy에서는 확인 된 예외를 처리 (또는 다시 throw)하지 않으므로 서비스 메소드가 확인 된 예외를 throw하면 트랜잭션이 롤백되지 않을 위험이 있습니다. 이것의 계정에, 다음과 같다 Grails 서비스 트랜잭션 동작

@Transactional(rollbackFor = Throwable.class) 
class MyService { 

    void writeSomething() { 
    } 
} 

나는 단지 DB를 읽고 그 중 하나 MyService의 다른 방법을 가지고 가정, 그리고 다른 하나는 DB에 접촉하지 않는 모든 Grails의 서비스 클래스를 주석을 바람직하다고 특수 효과가 맞습니까? 예외가 어떤 방법에서 발생합니다

  • 경우와 진행중인 트랜잭션이, 그것은 것입니다 : 당신이 내 의도가 무엇인지 알아야합니다 추측이 질문에 대답하기 위해

    @Transactional(readOnly = true) 
    void readSomething() {} 
    
    // Maybe this should be propagation = Propagation.NOT_SUPPORTED instead? 
    @Transactional(propagation = Propagation.SUPPORTS) 
    void dontReadOrWrite() {} 
    

    롤백 할 수 있습니다. 예를 들어, writeSomething()dontReadOrWrite()을 호출하고 후자의 예외가 발생하면 전자에서 시작한 트랜잭션은 롤백됩니다. 난 명시 적으로 무시하지 않는 한 rollbackFor 클래스 수준 특성이 개별 메서드에 의해 상속된다고 가정합니다.

  • 진행중인 트랜잭션이 없다면 readSomething()가 호출 될 때 어떤 트랜잭션이 읽기 전용 트랜잭션이 시작되고, 진행하지 않는 경우, 하나 dontReadOrWrite
  • 같은 방법을 위해 시작되지 않습니다. 읽기 - 쓰기 트랜잭션이 진행 중이면이 트랜잭션에 참여합니다.

답변

1

당신이 찾고있는 것은보다 세분화 된 트랜잭션 관리이며, @Transactional 어노테이션을 사용하는 것이 올바른 방향이라고 생각합니다. 즉, 당신이 찾고있는 행동을 줄 수있는 Grails Transaction Handling Plugin이 있습니다. 주의해야 할 점은 서비스 메소드 호출을 DomainClass.withTransaction 클로저로 랩핑하고 찾고있는 비표준 동작을 withTransaction() 메소드에 대한 매개 변수 맵핑으로 제공해야한다는 것입니다.

참고로 백엔드에서는 런타임시 트랜잭션의 동작을 변경하기 위해 @Transactional 주석을 사용하여 위에서 설명한 내용을 정확하게 수행합니다. 플러그인 문서는 훌륭하기 때문에 충분한 지침 없이는 자신을 찾을 수 없을 것이라고 생각합니다.

희망하시는 바입니다.

4

귀하의 코드는 가능한 한 정확합니다. 서비스 클래스의 개별 메소드에 Spring @Transactional 어노테이션을 사용하여 찾고자하는 세밀도를 얻으려면 원하는 지원이 필요합니다. dontReadOrWrite (NOT_SUPPORTED는 기존 트랜잭션을 일시 중단하여 설명했던 내용을 기반으로 소프트웨어를 구입하지 않으며 소프트웨어에 사이클을 소비해야하므로 아무런 이득이 없으므로 고통이 있습니다.) 기본값을 원한다면 readSomething에 대한 전파 동작 (필수).

Spring 트랜잭션 동작에서 유의해야 할 점은 Spring은 적절한 트랜잭션 설정을 수행하는 프록시에 클래스를 래핑하여 트랜잭션 관리를 구현하고 메소드를 호출 한 다음 적절한 트랜잭션을 해체 할 때 제어가 반환됩니다. 그리고 중요한(),이 트랜잭션 관리 코드 경우에만 writeSomething() dontReadOrWrite() 첫 번째 글 머리 기호를 직접 호출하는 경우 발생하지 않는 프록시에서 메서드를 호출 할 때 호출됩니다.

  1. 이동 : 당신이, 당신은 당신이 트랜잭션 관리를위한 Spring의 @Transactional 주석을 계속 사용하려면 알고있는 두 가지 선택을 가지고 다른 방법으로 불리는 방법에 다른 트랜잭션 동작을해야하는 경우

    이 메소드는 다른 서비스 클래스로 호출되어 스프링 프록시를 통해 원래 서비스 클래스에서 액세스됩니다.

  2. 방법을 그대로 둡니다. 서비스 클래스의 멤버 변수를 서비스 클래스의 인터페이스와 동일한 유형으로 선언하고 @Autowired로 만들어 서비스 클래스의 Spring 프록시 객체에 대한 참조를 제공합니다. 그런 다음 다른 트랜잭션 동작을 사용하여 메소드를 호출하려는 경우 해당 멤버 변수에서 직접 수행하지 말고 Spring 트랜잭션 코드가 원하는대로 실행됩니다. 그것은 당신의 코드를 유지 끝나는 누구든지 혼란없이 문제를 해결하기 때문에 두 가지 방법이 정말 어쨌든 관련이없는 경우

접근 # 1 중대하다, 실수로 트랜잭션 지원 메소드를 호출하는 것을 잊지 수있는 방법은 없습니다 .

일반적으로 Approach # 2가 더 나은 옵션입니다. 즉, 메소드가 모두 동일한 서비스에 있고 사용자가 실제로 분리되어 있지 않다고 가정 할 때입니다. 그러나 Spring 트랜잭션의이 주름을 이해하지 못하는 관리자에게 혼란 스럽습니다. 호출하는 각 장소에서 그렇게 호출해야한다는 것을 기억해야합니다. 따라서 가격이 책정됩니다. 나는 보통 서비스 클래스를 비정상적으로 분해하지 않기 위해 그 가격을 기꺼이 지불 할 것이지만 항상 그렇듯이 그것은 당신의 상황에 달려 있습니다.