복붙노트

[SPRING] 새 트랜잭션 범위 내에서 개체 업데이트

SPRING

새 트랜잭션 범위 내에서 개체 업데이트

거래상의 경계와 관련된 문제가 있으며 무엇이 잘못 될지 알 수 없습니다.

@Transactional( propagation = Propagation.REQUIRED )
Class A {
void methodA() {
     try {
     new B().callMethodB(obj)
     } catch(Exception e) {
           updateSomeProperty(obj1)
     }
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
void updateSomeProperty(Object obj1) {
     obj1.setProperty(1);
     obj1.save();       
}
        }

 Class B {

   public void callMethodB(Object obj) throws Exception {
    throws new Exception();  
 }

 }

문제는 오류가 발생할 때 내 개체가 업데이트되지 않는 것입니다. 또한 updateSomeProperty 메서드 내에서 SQL 코드 실행 시도했지만 그 또한 작동하지 않았다.

기본적으로 예외가 발생하더라도 개체의 속성을 업데이트하려고합니다. 어떤 아이디어?

해결법

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

    1.그리고 그것은 효과가 없어야합니다. 클래스의 다른 메서드에서 updateSomeProperty (obj1)를 호출하고 REQUIRED에서 REQUIRED_NEW로 기본 트랜잭션 동작을 변경하려고했기 때문입니다. 하지만 작동하지 않습니다. 예외가 발생할 때 모든 변경 사항이 롤백되는 이유가 여기 있습니다.

    그리고 그것은 효과가 없어야합니다. 클래스의 다른 메서드에서 updateSomeProperty (obj1)를 호출하고 REQUIRED에서 REQUIRED_NEW로 기본 트랜잭션 동작을 변경하려고했기 때문입니다. 하지만 작동하지 않습니다. 예외가 발생할 때 모든 변경 사항이 롤백되는 이유가 여기 있습니다.

    기본적으로 Spring은 인터페이스 용 프록시를 만들고 @Transactional annotation은 공용 메소드에만 사용해야합니다. 그리고이 메서드는 "외부"에서 호출해야합니다. 클래스 내의 다른 메소드에서 호출하면 @Transactional 주석은 작동하지 않습니다.

    xml의 ​​트랜잭션에 대한 기본 설정을 변경할 수도 있습니다 (속성 proxy-target-class 및 mode 참조). 그러나 나는 이것을 결코 바꾸지 않았으며 정확히 어떻게 작동해야 하는지를 기억하지 못합니다.

    <tx:annotation-driven transaction-manager="txManager" mode="..." proxy-target-class="..."/>
    

    편집하다:

    그건 그렇고. 트랜잭션 함정에 관한 아주 좋은 기사입니다. 그것은 나를 많이 도왔다. 트랜잭션에 관한 다른 매우 흥미로운 기사도 거의 없습니다.

    편집 2 :

    다시 안녕하세요. 나는 당신의 문제에 대한 해결책을 찾았다 고 생각합니다. 적어도 나는 이것을 테스트했고 잘 작동한다. 트랜잭션 모드를 "AspectJ"로 변경하고 AspectJ 컴파일 시간을 프로젝트에 사용하도록 제안했다. 이렇게하면 변경된 트랜잭션 동작 (시작된 중첩 트랜잭션)으로 한 클래스 내의 다른 메서드에서 개인 트랜잭션 메서드를 호출 할 수 있습니다. 이 경우 외부 트랜잭션이 롤백되는 동안 중첩 트랜잭션의 일부 변경 내용을 커밋 할 수 있습니다. 이를 위해 다음과 같은 단계를 수행해야합니다.

    1) 트랜잭션 정의에서 트랜잭션 모드 변경 : - xml 구성을 사용하는 경우 :

    <tx:annotation-driven transaction-manager="txManager" mode="aspectj"/>
    

    2) pom에 aspectj 의존성을 추가합니다.

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>${aspectj.version}</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>${aspectj.version}</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjtools</artifactId>
        <version>${aspectj.version}</version>
    </dependency>
    

    3) pom에 스프링 측면 의존성 추가 :

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>3.1.2.RELEASE</version>
        <scope>compile</scope>
    </dependency>
    

    4) 컴파일 시간 잡기를 가능하게하는 maven plugin을 추가한다.

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.4</version>
                <configuration>
                    <showWeaveInfo>true</showWeaveInfo>
                    <source>${compiler.version}</source>
                    <target>${compiler.version}</target>
                    <Xlint>ignore</Xlint>
                    <complianceLevel>${compiler.version}</complianceLevel>
                    <encoding>UTF-8</encoding>
                    <verbose>false</verbose>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <!-- <goal>test-compile</goal> -->
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
    

    5) 또한 내 pom thats에서 내가 왜 그것을 추가하는 것이 더 beter 생각하는 플러그인을 maven 컴파일해야 :

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <compilerVersion>${compiler.version}</compilerVersion>
            <fork>true</fork>
            <source>1.7</source>
            <target>1.7</target>
        </configuration>
    </plugin>
    

    * 참고 : jdk 버전 1.7 이상을 사용합니다. 그리고 컴파일러와 aspectj의 제 버전은 매우 좋습니다.

    <compiler.version>1.7</compiler.version>
    <aspectj.version>1.6.12</aspectj.version>
    

    또한 나는 다른 버전의 라이브러리를 가지고있다. (그러나 이것이 필요하지는 않다) :

    <org.springframework.version>3.1.0.RELEASE</org.springframework.version>
    <org.hibernate.version>4.1.0.Final</org.hibernate.version>
    <org.springdata.version>1.0.2.RELEASE</org.springdata.version>
    

    봄에는 로딩 타임을 사용하려고 할 수도 있지만 구성하기가 더 어렵습니다 (이것은 제 견해입니다). 프로덕션에서 사용하는 것은 권장되지 않습니다 (몇몇 게시물에서 읽었을 때). 그러나 당신이 그것을 사용하기로 결정한다면 당신은 웹과 봄 참조 dicumentation에 많은 정보를 찾을 수 있습니다.

    당신이 maven없이 컴파일 시간을 사용하고 싶다면 이것을 설정하는 방법을 모른다. (필자는 메이븐에서만 테스트했다.) 웹에서 이러한 정보를 찾을 수는 있지만 종속성을 처리하는 것이 훨씬 쉽기 때문에 (그리고이 예에서는 필요한 플러그인을 추가하기 위해) Maven을 사용하는 것이 좋습니다.

    다음은 테스트를 위해 사용한 예제입니다.

    catch 블록에서 예외를 rethrow (나는 상위 클래스에서 처리 할 필요가 없기 때문에 이것을 Runtime 예외로한다.). 올바른 외부 트랜잭션 롤백에 필요합니다.

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

    2.@Transactional 사용법은 Spring Reference를 참조하십시오. @ 트랜잭션은 스프링 프록시를 사용할 때 많은 ** 조건이 적용될 때 코드에 적용하기 전에 이해해야합니다.

    @Transactional 사용법은 Spring Reference를 참조하십시오. @ 트랜잭션은 스프링 프록시를 사용할 때 많은 ** 조건이 적용될 때 코드에 적용하기 전에 이해해야합니다.

  3. ==============================

    3.noRollbackFor = RuntimeException.class 또는 원하는 다른 클래스를 지정해 주시겠습니까? 그러면 데이터베이스를 업데이트 할 수 있기를 바랍니다. 즉, @ Transactional (noRollbackFor = RuntimeException.class)

    noRollbackFor = RuntimeException.class 또는 원하는 다른 클래스를 지정해 주시겠습니까? 그러면 데이터베이스를 업데이트 할 수 있기를 바랍니다. 즉, @ Transactional (noRollbackFor = RuntimeException.class)

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

    4.위의 배열은 새로운 트랜잭션을 시작하고 원래 트랜잭션과 다른 다른 작업을 수행하는 데 적합합니다.

    위의 배열은 새로운 트랜잭션을 시작하고 원래 트랜잭션과 다른 다른 작업을 수행하는 데 적합합니다.

    내 경우에 잘못되어 가고있는 한 가지는 다른 트랜잭션에서 두 번째 트랜잭션이 다시 롤백되는 예외를 던지고 있다는 것입니다.

    So The thing is beware off exception in the transaction because they ensure that the database state rolls back. It is for what they are meant for.   
    

    감사

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

    5.사용자 정의 예외를 생성하고 던져 사용, 또한 사용자 정의 예외를 정의하는 동안 클래스 수준의 주석으로 @ApplicationException (롤백 = false)를 사용하십시오.

    사용자 정의 예외를 생성하고 던져 사용, 또한 사용자 정의 예외를 정의하는 동안 클래스 수준의 주석으로 @ApplicationException (롤백 = false)를 사용하십시오.

    e.

    @ApplicationException(rollback=false)
    public CustomException extends Exception{
    
  6. from https://stackoverflow.com/questions/11796584/update-an-object-within-new-transactional-scope by cc-by-sa and MIT license