문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판 이전 판 다음 판 | 이전 판 다음 판 양쪽 다음 판 | ||
springframework:transaction [2014/07/28 13:01] kwon37xi |
springframework:transaction [2021/10/13 14:09] kwon37xi |
||
---|---|---|---|
줄 1: | 줄 1: | ||
====== Spring Transaction ====== | ====== Spring Transaction ====== | ||
+ | * [[springframework: | ||
+ | * [[http:// | ||
* [[http:// | * [[http:// | ||
+ | |||
+ | ===== 내부 트랜잭션 메소드 호출 금지 ===== | ||
+ | * 기본 프록시 모드에서는 클래스의 메소드에서 동일 클래스의 '' | ||
+ | * 이는 AOP의 기본작동이 그렇기 때문이다. | ||
+ | * 따라서 항상 트랜잭션을 올바로 적용하려면 **현재 클래스의 메소드가 아닌 다른 클래스의 메소드에 트랜잭션을 걸어야만 한다.** | ||
+ | |||
+ | > In proxy mode (which is the default), **only external method calls coming in through the proxy are intercepted. This means that self-invocation, | ||
+ | |||
+ | ===== Circular (Cyclic) Dependency 금지 ===== | ||
+ | * Circular Dependency 인 Bean에 '' | ||
+ | * 이는 대부분의 AOP에서 동일하게 적용될 것으로 보임. Circular Dependency 를 항상 피하도록 한다. | ||
+ | |||
+ | ===== interface or class? ===== | ||
+ | * '' | ||
+ | * **Spring 문서는 class에 트랜잭션 애노테이션 걸기를 권장**하고 있다. | ||
+ | |||
+ | > Spring recommends that you **only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation**, | ||
+ | |||
===== Read Only ===== | ===== Read Only ===== | ||
- | * [[http://www.codeinstructions.com/2009/ | + | * [[http://akaroice.tistory.com/20|hibernate flush VS commit :: 비상]] |
- | '' | + | '' |
이 힌트로 정말로 read only 트랜잭션이 생성될 수도 있고, MySQL 리플리케이션 JDBC 드라이버의 경우 Write가 있을 경우에는 Master로 read only일 경우에는 Slave로 커넥션을 맺는 식의 선택을 하는 정도의 역할만 할 수도 있다. | 이 힌트로 정말로 read only 트랜잭션이 생성될 수도 있고, MySQL 리플리케이션 JDBC 드라이버의 경우 Write가 있을 경우에는 Master로 read only일 경우에는 Slave로 커넥션을 맺는 식의 선택을 하는 정도의 역할만 할 수도 있다. | ||
줄 21: | 줄 41: | ||
* JTA 수준은 아니더라도 여러 트랜잭션이 생성되는 애플리케이션에서 각자 '' | * JTA 수준은 아니더라도 여러 트랜잭션이 생성되는 애플리케이션에서 각자 '' | ||
* Chained Transaction Manager로 묶이는 **각 트랜잭션의 Connection Pool 의 min/max 갯수는 동일하게** 가져가야한다. | * Chained Transaction Manager로 묶이는 **각 트랜잭션의 Connection Pool 의 min/max 갯수는 동일하게** 가져가야한다. | ||
+ | * 경험상, 서로 다른 동기화 시점을 가지는 트랜잭션은 묶지 않는 것이 좋다. | ||
+ | * MQ 사용시, MQ로 받은 데이터를 저장하는데 DB 접속이 끊겼을 경우 retry 를 하고자 한다면 MQ 트랜잭션과 DB 트랜잭션을 함께 묶으면 이 작업이 안된다. DB 트랜잭션이 롤백 될때 MQ 트랜잭션까지 롤백 되어 버려서 재시도할 트랜잭션이 없어지기 때문이다. | ||
===== Transaction 정보 처리 ===== | ===== Transaction 정보 처리 ===== | ||
* [[http:// | * [[http:// | ||
줄 58: | 줄 79: | ||
} | } | ||
</ | </ | ||
- | * 익명 클래스에서 트랜잭션을 올바로 걸고자 한다면 트랜잭션이 없는 외부에서 익명 클래스를 생성하면서 트랜잭션이 있는 서비스 Bean을 그 안으로 넘겨주어야 한다. | + | * 익명 클래스에서 트랜잭션을 올바로 걸고자 한다면 트랜잭션이 없는 외부에서 익명 클래스를 생성하면서 트랜잭션이 있는 서비스 Bean을 그 안으로 넘겨주어야 한다.< |
+ | // BookAnotherService | ||
+ | @Autowired | ||
+ | private BookService bookService; | ||
+ | |||
+ | @Transactional(readOnly = true) | ||
+ | public Iterable< | ||
+ | // true | ||
+ | log.info(" | ||
+ | return new Iterable< | ||
+ | @Override | ||
+ | public Iterator< | ||
+ | // false -> Transaction 영역이 아니므로 false가 맞음. | ||
+ | log.info(" | ||
+ | return bookService.findAllReal().iterator(); | ||
+ | } | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | // BookService | ||
+ | @Override | ||
+ | @Transactional(readOnly = true) | ||
+ | public List< | ||
+ | // true | ||
+ | log.info(" | ||
+ | return bookRepository.findAll(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Timeout ===== | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | ===== TransactionTemplate ===== | ||
+ | * Progmatic transaction demarcation. | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[http:// | ||
+ | * '' | ||
+ | |||
+ | ===== 참여 중인 트랜잭션이 실패하면 기본정책이 전역롤백 ===== | ||
+ | * [[http:// | ||
+ | * A -> B 메소드 호출되고 **A** 메소드에서 트랜잭션 시작되고 B 도 '' | ||
+ | * Hibernate의 경우 Hibernate 메소드 호출시 롤백 되면 무조건 롤백 마킹해버린다. | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | ===== Programatic Transaction Management ===== | ||
+ | * [[https:// | ||
+ | * API와 DB 호출이 한 트랜잭션으로 엮이거나 하면 커넥션 점유 시간이 증가하면서 커넥션 부족에 시달릴 수 있다. | ||
+ | * 또한 하나의 Bean 에서 트랜잭션이 없는 메소드가 트랜잭션이 있는 메소드를 호출 할 경우 작동하지 않는다. | ||
+ | * 이를 '' | ||
+ | * [[https:// | ||