사용자 도구

사이트 도구


springframework:transaction

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판 이전 판
다음 판
이전 판
springframework:transaction [2015/09/03 10:40]
kwon37xi
springframework:transaction [2022/11/09 14:45] (현재)
kwon37xi [Spring Transaction]
줄 1: 줄 1:
 ====== Spring Transaction ====== ====== Spring Transaction ======
   * [[springframework:javaconfig:enabletransactionmanagement|Spring Framework @EnableTransactionManagement]]   * [[springframework:javaconfig:enabletransactionmanagement|Spring Framework @EnableTransactionManagement]]
 +  * [[http://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html|SpringFramework Transaction Management Reference]]
   * [[http://www.ibm.com/developerworks/java/library/j-ts1/index.html|Transaction strategies: Understanding transaction pitfalls]]   * [[http://www.ibm.com/developerworks/java/library/j-ts1/index.html|Transaction strategies: Understanding transaction pitfalls]]
 +  * [[https://www.baeldung.com/spring-transactional-propagation-isolation|Transaction Propagation and Isolation in Spring @Transactional | Baeldung]]
 +
 +===== 내부 트랜잭션 메소드 호출 금지 =====
 +  * 기본 프록시 모드에서는 클래스의 메소드에서 동일 클래스의 ''@Transactional'' 걸린 메소드를 호출하면 트랜잭션이 무시된다.
 +  * 이는 AOP의 기본작동이 그렇기 때문이다.
 +  * 따라서 항상 트랜잭션을 올바로 적용하려면 **현재 클래스의 메소드가 아닌 다른 클래스의 메소드에 트랜잭션을 걸어야만 한다.**
 +
 +> In proxy mode (which is the default), **only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction** at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. @PostConstruct.
 +
 +===== Circular (Cyclic) Dependency 금지 =====
 +  * Circular Dependency 인 Bean에 ''@Transactional'' 애노테이션을 줘도 트랜잭션이 먹지 않는 현상이 발견됨(Spring 3.x).
 +  * 이는 대부분의 AOP에서 동일하게 적용될 것으로 보임. Circular Dependency 를 항상 피하도록 한다.
 +
 +===== interface or class? =====
 +  * ''@Transactional'' 어노테이션을 어디에 걸어야 하는가?
 +  * **Spring 문서는 class에 트랜잭션 애노테이션 걸기를 권장**하고 있다.
 +
 +> Spring recommends that you **only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation**, as opposed to annotating interfaces. You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies ( proxy-target-class="true") or the weaving-based aspect ( mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.
 +
  
 ===== Read Only ===== ===== Read Only =====
-  * [[http://www.codeinstructions.com/2009/04/read-only-transactions-with-spring-and.html|Read-Only transactions with Spring and Hibernate]] 참조.+  * [[http://akaroice.tistory.com/20|hibernate flush VS commit :: 비상]]
  
-''@Transactional(readOnly=true)''는 JDBC의 ''[[http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/Connection.html#setReadOnly%28boolean%29|Connection.setReadOnly(true)]]''를 호출한다. 이는 단지 **"힌트"일 뿐이며 실제 데이터베이스 자체를 read-only 트랜잭션으로 생성할지 여부는 JDBC 드라이버에 따라 달라지고 행위도 데이터 계층 프레임워크의 구현여부에 따라 달라질 수 있다.**+''@Transactional(readOnly=true)''는 JDBC의 ''[[https://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html#setReadOnly(boolean)|Connection.setReadOnly(true)]]''를 호출한다. 이는 단지 **"힌트"일 뿐이며 실제 데이터베이스 자체를 read-only 트랜잭션으로 생성할지 여부는 JDBC 드라이버에 따라 달라지고 행위도 데이터 계층 프레임워크의 구현여부에 따라 달라질 수 있다.**
  
 이 힌트로 정말로 read only 트랜잭션이 생성될 수도 있고, MySQL 리플리케이션 JDBC 드라이버의 경우 Write가 있을 경우에는 Master로 read only일 경우에는 Slave로 커넥션을 맺는 식의 선택을 하는 정도의 역할만 할 수도 있다. 이 힌트로 정말로 read only 트랜잭션이 생성될 수도 있고, MySQL 리플리케이션 JDBC 드라이버의 경우 Write가 있을 경우에는 Master로 read only일 경우에는 Slave로 커넥션을 맺는 식의 선택을 하는 정도의 역할만 할 수도 있다.
줄 12: 줄 32:
 Oracle JDBC 드라이버는 Read-Only 트랜잭션을 지원하며, MySQL의 경우  5.6.5 버전이 되어서야 이를 지원하게 되었다. Oracle JDBC 드라이버는 Read-Only 트랜잭션을 지원하며, MySQL의 경우  5.6.5 버전이 되어서야 이를 지원하게 되었다.
  
-Spring-Hibernate 연동시에는 Session의 Flush Mode를 ''FLUSH_NEVER''로 변경한다. 그러나 데이터가 수정되면 수정된 상태로 세션의 1차 캐시에는 수정된 상태로 데이터가 남아있게 되면, 명시적으로 ''flush()''를 호출하면 쓰기 기능이 작동하게 된다.+Spring-Hibernate 연동시에는 Session의 Flush Mode를 ''FLUSH_NEVER''로 변경한다. 그러나 데이터가 수정되면 수정된 상태로 세션의 1차 캐시에는 수정된 상태로 데이터가 남아있게 되면, 명시적으로 ''flush()''를 호출해야 쓰기 기능이 작동하게 된다.
  
  
줄 26: 줄 46:
 ===== Transaction 정보 처리 ===== ===== Transaction 정보 처리 =====
   * [[http://docs.spring.io/spring/docs/3.2.10.RELEASE/javadoc-api/org/springframework/transaction/interceptor/TransactionAspectSupport.html|org.springframework.transaction.interceptor.TransactionAspectSupport]]   * [[http://docs.spring.io/spring/docs/3.2.10.RELEASE/javadoc-api/org/springframework/transaction/interceptor/TransactionAspectSupport.html|org.springframework.transaction.interceptor.TransactionAspectSupport]]
-  * [[http://docs.spring.io/spring/docs/3.2.10.RELEASE/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationManager.html|TransactionSynchronizationManager]]+  * [[http://docs.spring.io/spring/docs/3.2.10.RELEASE/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationManager.html|TransactionSynchronizationManager]] : 현재 쓰레드의 트랜잭션에 관한 많은 사항을 확인할 수 있다.
   * [[http://docs.spring.io/spring/docs/3.2.10.RELEASE/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationUtils.html|TransactionSynchronizationUtils]]   * [[http://docs.spring.io/spring/docs/3.2.10.RELEASE/javadoc-api/org/springframework/transaction/support/TransactionSynchronizationUtils.html|TransactionSynchronizationUtils]]
   * [[http://stackoverflow.com/questions/13395794/how-do-i-get-transaction-info-in-spring-whether-transaction-is-commited-or-rollb|hibernate - how do i get transaction info in spring whether transaction is commited or rollback in a declartive transaction management]]<code java>   * [[http://stackoverflow.com/questions/13395794/how-do-i-get-transaction-info-in-spring-whether-transaction-is-commited-or-rollb|hibernate - how do i get transaction info in spring whether transaction is commited or rollback in a declartive transaction management]]<code java>
줄 93: 줄 113:
   * ''@Transactional(timeout="")''을 통해서 각 단위별로 지정가능하다.   * ''@Transactional(timeout="")''을 통해서 각 단위별로 지정가능하다.
  
 +===== Programatic Transaction Managemen - TransactionTemplate =====
 +  * Progmatic transaction demarcation.
 +  * API와 DB 호출이 한 트랜잭션으로 엮이거나 하면 커넥션 점유 시간이 증가하면서 커넥션 부족에 시달릴 수 있다.
 +  * 또한 하나의 Bean 에서 트랜잭션이 없는 메소드가 트랜잭션이 있는 메소드를 호출 할 경우 작동하지 않는다.
 +  * 이를 ''@Transactional'' 애노테이션으로 해결하려 들면 복잡도만 더 증가한다.
 +  * [[https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/support/TransactionTemplate.html|TransactionTemplate]] 객체를 생성해서 해결하는게 더 깔끔하다.
 +  * [[https://www.baeldung.com/spring-programmatic-transaction-management|Programmatic Transaction Management in Spring | Baeldung]]
 +  * [[http://www.simplespringtutorial.com/springProgrammaticTransactions.html|Spring Programmatic Transactions]]
 +  * [[https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/support/TransactionTemplate.html|TransactionTemplate]]
 +  * [[https://www.logicbig.com/tutorials/spring-framework/spring-data-access-with-jdbc/programmatic-transaction.html|Spring - Programmatic Transaction]]
 +  * [[http://wikibook.co.kr/article/transaction-management-using-spring/|스프링을 이용한 트랜잭션 관리]]
 +  * ''TransactionTemplate''은 속성이 동일할 경우 재사용 가능하므로 동일 속성에 대해 하나의 객체만 만들어서 재사용하면 된다.
 +  * [[https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/interceptor/RuleBasedTransactionAttribute.html|RuleBasedTransactionAttribute]] 와 조합하면 복잡한 트랜잭션 규칙을 만들어 낼 수 있을 것 같지만 사실은 아니다. 해당 클래스의 복잡한 설정값을 모두 제거한 [[https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/TransactionDefinition.html|TransactionDefinition]]을 사용해서 처리한다.
 +
 +===== 참여 중인 트랜잭션이 실패하면 기본정책이 전역롤백 =====
 +  * [[http://woowabros.github.io/experience/2019/01/29/exception-in-transaction.html|응? 이게 왜 롤백되는거지? - 우아한형제들 기술 블로그]]
 +  * A -> B 메소드 호출되고 **A** 메소드에서 트랜잭션 시작되고 B 도 ''@Transactional(propagation=REQUIRED)''일 경우, B에서 예외가 발생하면 A에서 비록 예외를 잡아서 먹어버리더라도 트랜잭션은 롤백 된다.
 +  * Hibernate의 경우 Hibernate 메소드 호출시 롤백 되면 무조건 롤백 마킹해버린다.
 +  * [[https://github.com/spring-projects/spring-framework/blob/4560dc2818ae1d5e1bc5ceef89f1b6870700eb1f/spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java#L265|globalRollbackOnParticipationFailure]]
 +  * [[https://dzone.com/articles/most-common-spring-transactional-mistakes|Spring @Transactional Mistakes Everyone Makes - DZone Java]]
springframework/transaction.1441246201.txt.gz · 마지막으로 수정됨: 2015/09/03 10:40 저자 kwon37xi