이 기사는 Spring의 거래 관리에 대한 심층적 인 연구를 수행 할 것입니다. 주로 @transactional이 맨 아래에서 어떻게 작동하는지 소개합니다. 다음 기사가 소개합니다.
전파 (트랜잭션 전파) 및 격리 (격리)와 같은 속성 사용
거래 사용의 함정은 무엇이며 피하는 방법
JPA 및 거래 관리
JPA 자체는 어떤 종류의 선언적 거래 관리를 제공하지 않는 것이 중요합니다. 종속성 분사 컨테이너 외부에서 JPA를 사용하는 경우 트랜잭션은 개발자가 프로그래밍 방식으로 구현해야합니다.
userTransaction UTX = entityManager.getTransaction (); try {utx.begin (); businessLogic (); utx.commit ();} catch (예외) {utx.rollback (); strowEx;}이러한 트랜잭션 관리 방식은 트랜잭션 범위를 코드에 명확하게 표현할 수 있지만 다음과 같은 단점이 있습니다.
반복 된 코드와 오류가 발생하기 쉽습니다
모든 오류가 더 큰 영향을 줄 수 있습니다
오류는 디버깅하고 재현하기가 어렵습니다
코드 기반의 가독성을 줄입니다
방법이 다른 트랜잭션 방법을 호출하면 어떻게됩니까?
스프링 @transactional 사용
Spring @transactional을 사용하면 위의 코드가 단순화됩니다.
@Transactional PublicVoid BusinessLogic () {... 트랜잭션 내에서 엔티티 관리자 사용 ...}이 코드는 더 간결하고 읽을 수 있으며 현재 봄에 처리하는 권장 방법이기도합니다.
트랜잭션 전파와 같은 많은 중요한 측면은 @transactional을 사용하여 자동으로 처리 할 수 있습니다. 이 경우 BusinessLogic ()가 다른 트랜잭션 메소드를 호출하면이 메소드는 옵션을 기반으로 실행중인 거래에 가입하는 방법을 결정합니다.
이 강력한 메커니즘의 잠재적 인 단점 중 하나는 기본 작동을 숨기고 제대로 작동하지 않을 때 디버깅하기가 어렵다는 것입니다.
@transactional 의미
@Transactional의 주요 요점 중 하나는 두 가지 개별 개념을 고려하는 것입니다. 두 가지 개념은 모두 고유 한 범위와 수명주기입니다.
지속성 컨텍스트 (지속성 컨텍스트)
데이터베이스 트랜잭션
@transactional 자체는 단일 트랜잭션의 범위를 정의합니다. 이 거래는 지속 컨텍스트의 범위 내에 있습니다.
JPA의 지속성 컨텍스트는 EntityManager이며 내부 구현은 최대 절전 모드 세션을 사용합니다 (최대 절전 모드를 지속성 제공 업체로 사용).
Persistence 컨텍스트는 유한 한 컬렉션의 Java 객체의 상태를 기록하는 동기식 객체 일뿐 아니라 이러한 객체의 변경이 궁극적으로 데이터베이스에 지속되도록합니다.
이것은 단일 거래와 매우 다른 개념입니다. 엔티티 관리자는 여러 거래에서 사용될 수 있으며 실제로 이러한 방식으로 사용됩니다.
EntityManager는 언제 여러 거래에 걸쳐 있습니까?
가장 일반적인 상황은 애플리케이션이 뷰 모드에서 열린 세션을 사용하여 게으른 초기화 예외를 처리하는 경우입니다. 이전 기사는이 접근법의 장점과 단점을 소개했습니다.
이 경우 뷰 계층에서 실행하는 여러 쿼리는 단일 트랜잭션 비즈니스 로직이 아닌 별도의 트랜잭션에 있지만 이러한 쿼리는 동일한 엔티티 관리자가 관리합니다.
또 다른 시나리오는 개발자가 지속성 컨텍스트를 persistenceContextType.extended로 표시하므로 여러 요청에 응답 할 수 있다는 것입니다.
EntityManager와 거래 간의 관계를 정의하는 방법은 무엇입니까?
이는 응용 프로그램 개발자가 선택하지만 JPA Entity Manager의 가장 일반적인 방법은 "애플리케이션 트랜잭션 당 엔티티 관리자"모드입니다. Entity Manager 주입의 일반적인 방법은 다음과 같습니다.
@PersistEnceContext privateentityManager em;
기본값은 "트랜잭션 당 엔티티 관리자"모드입니다. 이 모드에서 엔티티 관리자가 @transactional 메소드 내에서 사용되는 경우 메소드는 단일 트랜잭션에서 실행됩니다.
@persistenceContext는 어떻게 작동합니까?
다음 질문은 엔티티 관리자 수명주기가 짧고 요청 당 여러 엔티티 관리자가 필요하다고 가정 할 때 @PersistEnceContext가 컨테이너가 시작될 때만 엔티티 관리자를 주입하는 방법입니다.
대답은 다음과 같습니다. EntityManager는 인터페이스이며 스프링 Bean에 주입되는 것은 엔티티 관리자 자체가 아니라 런타임에서 특정 엔티티 관리자의 컨텍스트 인식 프록시 (컨텍스트 인식 프록시)입니다.
프록시에 일반적으로 사용되는 특정 클래스는 SharedEntityManagerInvocationHandler이며 디버거의 도움으로 확인할 수 있습니다.
그렇다면 @transactional은 어떻게 작동합니까?
EntityManager 인터페이스를 구현하는 지속적인 컨텍스트 프록시는 선언 트랜잭션 관리의 유일한 부분은 아니지만 실제로 세 가지 구성 요소를 포함합니다.
EntityManager 프록시 자체
거래 섹션
거래 관리자
이 세 부분과 그 상호 작용을 살펴보십시오.
거래 섹션
거래 섹션은 주석이 달린 비즈니스 방법 전후에 호출 할 수있는 "주변"섹션입니다. 섹션을 구현하는 특정 클래스는 TransactionInterceptor입니다.
거래 섹션에는 두 가지 주요 책임이 있습니다.
'이전'에서이 섹션은 호출 비즈니스 방법이 진행중인 거래 범위 내에서 실행되어야하는지 또는 새로운 독립 거래를 시작 해야하는지 결정하는 콜 포인트를 제공합니다.
'After'에서 섹션은 거래가 커밋, 롤백 또는 계속 실행되는지 확인해야합니다.
'이전'에서 트랜잭션 섹션 자체에는 의사 결정 논리가 포함되어 있지 않으며 새 거래를 시작하기로 한 결정은 거래 관리자에게 위임됩니다.
거래 관리자
거래 관리자는 다음 두 가지 문제를 해결해야합니다.
새 엔티티 관리자가 생성되어야합니까?
새로운 거래를 시작해야합니까?
여기에는 '이전'논리가 호출 될 때 트랜잭션 섹션을 결정해야합니다. 거래 관리자의 결정은 다음 두 가지 요점을 기반으로합니다.
거래가 진행되고 있습니다
트랜잭션 방법의 전파 속성 (예 : 요구 사항 _new는 항상 새로운 거래를 시작합니다).
트랜잭션 관리자가 새로운 트랜잭션을 작성하려고한다고 결정하면 다음과 같습니다.
1. 새 엔티티 관리자를 만듭니다
2. 강도 관리자가 현재 스레드에 묶여 있습니다.
3. 데이터베이스 연결 풀에서 연결을 얻습니다
4. 연결을 현재 스레드에 바인딩합니다
ThreadLocal 변수를 사용하여 엔티티 관리자와 데이터베이스 연결을 현재 스레드에 바인딩하십시오.
트랜잭션은 스레드에 저장 될 때 실행되며 더 이상 사용되지 않으면 트랜잭션 관리자가 청산 여부를 결정합니다.
현재 엔티티 관리자 및 데이터베이스 연결이 필요한 경우 프로그램의 모든 부분을 스레드에서 검색 할 수 있습니다.
EntityManager 프록시
EntityManager Proxy (이미 이전에 소개 됨)는 퍼즐의 마지막 부분입니다. 비즈니스 메소드가 EntityManager.persist ()를 호출하면 엔티티 관리자가 직접 호출하지 않습니다.
대신, 비즈니스 방법은 에이전트를 호출하여 현재 엔터티 관리자를 스레드에서 얻습니다. 앞에서 언급했듯이 트랜잭션 관리자는 엔티티 관리자를 스레드에 바인딩합니다.
@transactional 메커니즘의 다양한 부분을 이해 한 후에는 일반적으로 사용되는 스프링 구성을 구현하는 스프링 구성을 살펴 보겠습니다.
세 부분을 통합합니다
트랜잭션 주석이 올바르게 작동 할 수 있도록 세 부분을 결합하는 방법은 무엇입니까? 먼저 엔티티 관리자 공장을 정의하십시오.
이를 통해 지속성 컨텍스트 주석을 사용하여 엔티티 관리자 프록시를 주입 할 수 있습니다.
@configuration publicclass entitymanagerfactoryconfiguration {@autowired privateatasource dataSource; @bean (entityManagerFactory ") publicLocalContainerEntityManagerFactoryBean emf () {localContainerEntityManagerFactoryBean emf = ... emf.SetDatasOrce (emf.SetDatasOrce); Newstring [] { "your.package"}); emf.setjpavendoradapter (newHiberNateJPavendorAdapter ()); returnemf;}}다음 단계는 트랜잭션 관리자를 구성하고 클래스에 주석 @transactional에서 트랜잭션 패싯을 적용하는 것입니다.
@Configuration @EnableTransactionManagement Publicclass TransactionManagersconfig {@autowired entityManagerFactory emf; @autowired PrivateAtAsource DataSource; @Bean (name = "transactionManager") publicPlatFormTransactionManager transactionManager () {jpatransactionManager tm = NewJPatrAnsactionManager (); tm.setentityManagerFactory (EMF); tm.setDatasource (DataSource); returnm;}}주석 @EnableTransactionManagement는 @transactional에 의해 주석이 달린 클래스가 트랜잭션의 컷 어웨이에 둘러싸여 있음을 Spring에 알립니다. 이 방법으로 @transactional을 사용할 수 있습니다.
요약
Spring의 선언적 거래 관리 메커니즘은 매우 강력하지만 오용되거나 쉽게 구성 될 수 있습니다.
이 메커니즘과 같은 문제가 제대로 작동하지 않거나 예상되는 작동 결과를 달성하지 못하는 경우 내부 작업을 이해하는 것이 도움이됩니다.
기억해야 할 가장 중요한 것은 트랜잭션과 지속 컨텍스트, 각각 읽을 수없는 명백한 수명주기를 가진 두 가지 개념을 고려하는 것입니다.
위는 Spring @transactional의 작동 원리에 대한이 기사의 모든 내용입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!