[SPRING] Spring 빈에서 새로운 트랜잭션 시작하기
SPRINGSpring 빈에서 새로운 트랜잭션 시작하기
우리는 :
@Transactional(propagation = Propagation.REQUIRED)
public class MyClass implementes MyInterface { ...
MyInterface에는 go () 메소드가 있습니다.
go ()가 실행될 때 메소드가 완료되면 / 롤백을 수행하는 새 트랜잭션이 시작됩니다.
이제 우리는 MyTransactional (propagation = Propagation.REQUIRES_NEW)을 가진 MyClass에서 private 메소드를 호출한다고 가정 해 보겠습니다. Spring은 REQUIRES_NEW 주석을 "무시"하고 새로운 트랜잭션을 시작하지 않는 것으로 보입니다. 인터페이스 수준 (MyInterface)에서 작동하며 MyClass 메서드에 대한 호출을 차단하지 않습니다. 이것이 맞습니까?
go () 트랜잭션 내에서 새 트랜잭션을 시작할 수있는 방법이 있습니까? 트랜잭션이 REQUIRES_NEW로 설정된 다른 Spring 관리 Bean을 호출하는 유일한 방법은 무엇입니까?
업데이트 : 클라이언트가 클래스를 실행하지 않고 인터페이스를 참조하여 go ()를 실행할 때이를 추가합니다.
@Autowired
MyInterface impl;
impl.go();
해결법
-
==============================
1.Spring 레퍼런스 2.5부터 :
Spring 레퍼런스 2.5부터 :
따라서 Spring은 비공개 메소드에서 @Transactional 주석을 무시합니다.
또한,
따라서 메서드를 public으로 만들었더라도 같은 클래스의 메서드 내에서 호출하면 새 트랜잭션이 시작되지 않습니다.
트랜잭션 설정에서 aspectj 모드를 사용하여 트랜잭션 관련 코드가 클래스에 포함되고 런타임에 프록시가 작성되지 않도록 할 수 있습니다.
자세한 내용은 참조 문서를 참조하십시오.
이것을 할 수있는 또 다른 방법은 클래스 자체에서 클래스의 스프링 프록시를 가져 와서 이것보다는 메소드를 호출하는 것입니다 :
@Service @Transactional(propagation = Propagation.REQUIRED) public class SomeService { @Autowired private ApplicationContext applicationContext; private SomeService getSpringProxy() { return applicationContext.getBean(this.getClass()); } private void doSomeAndThenMore() { // instead of // this.doSometingPublicly(); // do the following to run in transaction getSpringProxy().doSometingPublicly(); } public void doSometingPublicly() { //do some transactional stuff here } }
-
==============================
2.@Transactional은 Spring AOP가 작동하는 방식 때문에 공개 메소드에있는 경우에만 주목됩니다.
@Transactional은 Spring AOP가 작동하는 방식 때문에 공개 메소드에있는 경우에만 주목됩니다.
그러나 원하는 경우 TransactionTemplate을 사용하여 프로그래밍 방식으로 새 트랜잭션을 시작할 수 있습니다 (예 :
TransactionTemplate txTemplate = new TransactionTemplate(txManager); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); txTemplate.execute(new TransactionCallback<Object>() { public Object doInTransaction(TransactionStatus status) { // do stuff } });
-
==============================
3.즉, 트랜잭션 동작을 달성하기 위해 프록시를 통해 메소드를 호출해야합니다. 질문에서 질문 할 때 동일한 빈에서 "REQUIRES_NEW"를 호출 할 수 있습니다. 그렇게하려면 "자기"참조를 만들어야합니다. 봄에는 그럴 수 없습니다. 너는 그것을 주입해야한다. @Resource 주석이 있습니다.
즉, 트랜잭션 동작을 달성하기 위해 프록시를 통해 메소드를 호출해야합니다. 질문에서 질문 할 때 동일한 빈에서 "REQUIRES_NEW"를 호출 할 수 있습니다. 그렇게하려면 "자기"참조를 만들어야합니다. 봄에는 그럴 수 없습니다. 너는 그것을 주입해야한다. @Resource 주석이 있습니다.
@Service("someService") public class ServieImpl implements Service { @Resource(name = "someService") Service selfReference; @Transactional public void firstMethod() { selfReference.secondMethod(); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void secondMethod() { //do in new transaction } }
firstMethod의 호출은 "this"가 아닌 "REQUIRES_NEW"트랜잭션이 작동하도록 프록시를 호출합니다.
from https://stackoverflow.com/questions/3037006/starting-new-transaction-in-spring-bean by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 고정 관념의 장점? (0) | 2019.03.01 |
---|---|
[SPRING] Spring HATEOAS 대 Spring 데이터 Rest (0) | 2019.03.01 |
[SPRING] Spring에서 주석이있는 제 3 자 클래스를 어떻게 자동으로 작성합니까? (0) | 2019.03.01 |
[SPRING] Java 예제 : Quartz를 사용한 동적 작업 스케줄링 (0) | 2019.03.01 |
[SPRING] 스프링 3 JSON (MVC 포함) (0) | 2019.03.01 |