Loading...
Spring Framework Reference Documentation 7.0.2의 JPA의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
org.springframework.orm.jpa package에서 제공되는 Spring JPA는
Java Persistence API를 Hibernate와의 통합과 유사한 방식으로 포괄적으로 지원하면서도
추가 기능을 제공하기 위해 기반 구현을 인식합니다.
Spring JPA 지원은 애플리케이션이 엔티티 매니저를 얻기 위해 사용하는 JPA EntityManagerFactory
를 설정하는 세 가지 방법을 제공합니다.
LocalEntityManagerFactoryBean 사용LocalContainerEntityManagerFactoryBean 사용LocalEntityManagerFactoryBean 사용이 옵션은 독립 실행형 애플리케이션 및 통합 테스트와 같은 단순 배포 환경에서만 사용할 수 있습니다.
LocalEntityManagerFactoryBean은 애플리케이션이 데이터 액세스에 JPA만 사용하는
단순 배포 환경에 적합한 EntityManagerFactory를 생성합니다.
factory bean은 JPA의 Java SE 부트스트래핑에 따른 JPA PersistenceProvider 자동 감지 메커니즘을 사용하며,
대부분의 경우 persistence unit name만 지정하면 됩니다.
다음 XML 예제는 이러한 bean을 구성합니다:
1<beans> 2 <bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> 3 <property name="persistenceUnitName" value="myPersistenceUnit"/> 4 </bean> 5</beans>
이러한 형태의 JPA 배포는 가장 단순하면서도 가장 제한적입니다. 기존 JDBC DataSource bean 정의를 참조할 수 없으며,
글로벌 트랜잭션에 대한 지원도 존재하지 않습니다.
또한, persistent class의 위빙(byte-code 변환)은 provider-specific하며, 시작 시 특정 JVM agent를 지정해야 하는 경우가 많습니다. 이 옵션은 JPA 명세가 설계된 독립 실행형 애플리케이션 및 테스트 환경에만 충분합니다.
이 옵션은 Jakarta EE 서버에 배포할 때 사용할 수 있습니다. 서버의 문서를 확인하여 서버의 기본값과 다른 provider를 허용하도록 커스텀 JPA provider를 서버에 어떻게 배포하는지 확인하십시오.
JNDI(예: Jakarta EE 환경)로부터 EntityManagerFactory를 얻는 것은
다음 예제에서 보듯이 XML 설정을 변경하는 문제입니다:
1<beans> 2 <jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/> 3</beans>
이 동작은 표준 Jakarta EE 부트스트래핑을 가정합니다. Jakarta EE 서버는
persistence unit(실제로는 애플리케이션 jar 내 META-INF/persistence.xml 파일)과
Jakarta EE 배포 서술자(예: web.xml) 내 persistence-unit-ref entry를 자동 감지하고
해당 persistence unit에 대한 환경 네이밍 컨텍스트 위치를 정의합니다.
이러한 시나리오에서 persistent class의 위빙(byte-code 변환)을 포함한
전체 persistence unit 배포는 Jakarta EE 서버의 몫입니다. JDBC
DataSource는 META-INF/persistence.xml 파일 내 JNDI 위치를 통해 정의됩니다.
EntityManager 트랜잭션은 서버의 JTA 서브시스템과 통합됩니다. Spring은 단지
얻어온 EntityManagerFactory를 사용하여 의존성 주입을 통해 애플리케이션 객체에 전달하고
persistence unit에 대한 트랜잭션을 관리합니다(일반적으로 JtaTransactionManager를 통해).
같은 애플리케이션에서 여러 persistence unit을 사용하는 경우, 이러한 JNDI에서 가져온
persistence unit의 bean name은 애플리케이션이 이를 참조하는 데 사용하는 persistence unit name과
일치해야 합니다(예: @PersistenceUnit 및 @PersistenceContext 어노테이션에서).
LocalContainerEntityManagerFactoryBean 사용이 옵션은 Spring 기반 애플리케이션 환경에서 full JPA capability를 위해 사용할 수 있습니다. 여기에는 Tomcat과 같은 웹 컨테이너, 독립 실행형 애플리케이션, 그리고 정교한 persistence requirement를 가진 통합 테스트가 포함됩니다.
LocalContainerEntityManagerFactoryBean은 EntityManagerFactory 설정에 대한
완전한 제어를 제공하며, 세밀한 커스터마이징이 필요한 환경에 적합합니다.
LocalContainerEntityManagerFactoryBean은 persistence.xml 파일, 제공된
dataSourceLookup 전략, 지정된 loadTimeWeaver를 기반으로 PersistenceUnitInfo 인스턴스를 생성합니다.
따라서 JNDI 밖의 커스텀 데이터 소스로 작업하고 위빙 프로세스를 제어하는 것이 가능합니다.
다음 예제는 LocalContainerEntityManagerFactoryBean의 typical bean 정의를 보여줍니다:
1<beans> 2 <bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 3 <property name="dataSource" ref="someDataSource"/> 4 <property name="loadTimeWeaver"> 5 <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/> 6 </property> 7 </bean> 8</beans>
다음 예제는 typical persistence.xml 파일을 보여줍니다:
1<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> 2 <persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL"> 3 <mapping-file>META-INF/orm.xml</mapping-file> 4 <exclude-unlisted-classes/> 5 </persistence-unit> 6</persistence>
<exclude-unlisted-classes/>shortcut은 어노테이션된 엔티티 클래스에 대한 스캐닝이 발생하지 않아야 함을 나타냅니다. 명시적인 'true' 값 (<exclude-unlisted-classes>true</exclude-unlisted-classes/>)도 스캔이 없음을 의미합니다.<exclude-unlisted-classes>false</exclude-unlisted-classes/>는 스캔을 트리거합니다. 그러나 엔티티 클래스 스캐닝이 발생하기를 원한다면exclude-unlisted-classeselement를 생략하는 것을 권장합니다.
LocalContainerEntityManagerFactoryBean을 사용하는 것은 가장 강력한 JPA 설정
옵션으로, 애플리케이션 내에서 유연한 로컬 설정을 허용합니다. 이는
기존 JDBC DataSource에 대한 링크를 지원하고, 로컬 및 글로벌 트랜잭션을 모두 지원하는 등
여러 기능을 제공합니다.
그러나 persistence provider가 byte-code 변환을 요구하는 경우, 위빙-capable 클래스 로더의 가용성과 같은 런타임 환경에 요구사항을 부과하기도 합니다.
이 옵션은 Jakarta EE 서버의 내장 JPA capability와 충돌할 수 있습니다. full Jakarta EE 환경에서는
JNDI로부터 EntityManagerFactory를 얻는 것을 고려하십시오.
또는
LocalContainerEntityManagerFactoryBean 정의에 커스텀 persistenceXmlLocation을 지정할 수 있습니다(예:
META-INF/my-persistence.xml) 그리고 애플리케이션 jar 파일에 해당 이름의 descriptor만 포함하십시오.
Jakarta EE 서버는 기본 META-INF/persistence.xml 파일만 찾기 때문에 그러한 커스텀 persistence unit을 무시하며,
따라서 Spring-driven JPA 설정과의 충돌을 미연에 방지합니다.
Load-time weaving은 언제 필요한가?
모든 JPA provider가 JVM agent를 요구하는 것은 아닙니다. Hibernate는 요구하지 않는 예입니다. provider가 agent를 요구하지 않거나 커스텀 컴파일러나 Ant task를 통한 빌드 타임 enhancement와 같은 다른 대안이 있는 경우, load-time weaver를 사용해서는 안 됩니다.
LoadTimeWeaver 인터페이스는 Spring이 제공하는 클래스로, JPA
ClassTransformer 인스턴스를 웹 컨테이너인지 애플리케이션 서버인지에 따라
특정 방식으로 플러그인할 수 있게 해줍니다. agent를
통해 ClassTransformer를 훅킹하는 것은 일반적으로 효율적이지 않습니다.
agent는 전체 가상 머신을 대상으로 작동하며, 로드되는 모든 클래스를 검사하는데, 이는 일반적으로 프로덕션 서버 환경에서는 바람직하지 않습니다.
Spring은 다양한 환경을 위한 여러 LoadTimeWeaver 구현을 제공하여,
ClassTransformer 인스턴스가 VM마다가 아니라 각 클래스 로더마다만 적용되도록 합니다.
LoadTimeWeaver 구현 및 그 설정(예: Tomcat, JBoss, WebSphere와 같은
여러 플랫폼에 대한 generic 또는 customized 설정)에 대한 보다 깊은 내용은
AOP 챕터의 Spring 설정을 참조하십시오.
Spring 설정에 설명된 것처럼
@EnableLoadTimeWeaving 어노테이션 또는 context:load-time-weaver XML element를 사용하여
컨텍스트 전체 LoadTimeWeaver를 구성할 수 있습니다. 이러한 글로벌 weaver는 모든 JPA
LocalContainerEntityManagerFactoryBean 인스턴스에 의해 자동으로 선택됩니다.
다음 예제는 platform(Tomcat의 위빙-capable 클래스 로더 또는 Spring의 JVM agent 등)에 대한 자동 감지와 모든 weaver-aware bean으로의 weaver 자동 전파를 제공하는 load-time weaver 설정의 선호되는 방식을 보여줍니다:
1<context:load-time-weaver/> 2 3<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 4 ... 5</bean>
그러나 필요한 경우, 다음 예제에서 보듯이 loadTimeWeaver property를 통해
dedicated weaver를 수동으로 지정할 수도 있습니다:
1<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 2 <property name="loadTimeWeaver"> 3 <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/> 4 </property> 5</bean>
LTW가 어떻게 구성되었든 간에, 이 기법을 사용하면 instrumentation에 의존하는 JPA 애플리케이션이 agent 없이 target platform(예: Tomcat)에서 실행될 수 있습니다. 이는 hosting 애플리케이션이 서로 다른 JPA 구현에 의존하는 경우 특히 중요합니다. 왜냐하면 JPA transformer는 클래스 로더 레벨에서만 적용되며, 따라서 서로 격리되기 때문입니다.
여러 persistence unit 위치(classpath 내 여러 JAR 등에 저장된)에 의존하는 애플리케이션을 위해,
Spring은 central repository로 동작하고 persistence unit discovery process(비용이 많이 들 수 있음)를
피하기 위해 PersistenceUnitManager를 제공합니다.
기본 구현은
여러 위치를 지정할 수 있게 해줍니다. 이러한 위치는 parse되어 이후 persistence unit name을 통해
검색됩니다. (기본적으로 classpath에서 META-INF/persistence.xml 파일이 검색됩니다.)
다음 예제는 multiple 위치를 구성합니다:
1<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"> 2 <property name="persistenceXmlLocations"> 3 <list> 4 <value>org/springframework/orm/jpa/domain/persistence-multi.xml</value> 5 <value>classpath:/my/package/**/custom-persistence.xml</value> 6 <value>classpath*:META-INF/persistence.xml</value> 7 </list> 8 </property> 9 <property name="dataSources"> 10 <map> 11 <entry key="localDataSource" value-ref="local-db"/> 12 <entry key="remoteDataSource" value-ref="remote-db"/> 13 </map> 14 </property> 15 <!-- if no datasource is specified, use this one --> 16 <property name="defaultDataSource" ref="remoteDataSource"/> 17</bean> 18 19<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 20 <property name="persistenceUnitManager" ref="pum"/> 21 <property name="persistenceUnitName" value="myCustomUnit"/> 22</bean>
기본 구현은 PersistenceUnitInfo 인스턴스를 커스터마이징할 수 있게 해주며
(JPA provider에 전달되기 전), 이는 선언적(모든 hosted unit에 영향을 미치는 property를 통해) 또는
프로그래밍 방식(PersistenceUnitPostProcessor를 통해 persistence unit selection을 허용)으로
가능합니다.
PersistenceUnitManager가 지정되지 않은 경우, 하나가 생성되어
LocalContainerEntityManagerFactoryBean 내부에서 사용됩니다.
LocalContainerEntityManagerFactoryBean은 다음 예제에서 보듯이
bootstrapExecutor property를 통해 background bootstrapping을 지원합니다:
1<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 2 <property name="bootstrapExecutor"> 3 <bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/> 4 </property> 5</bean>
실제 JPA provider 부트스트래핑은 지정된 executor로 넘겨진 다음,
애플리케이션 부트스트랩 스레드와 병렬로 실행됩니다. 노출된 EntityManagerFactory
프록시는 다른 애플리케이션 컴포넌트에 주입될 수 있으며, 심지어
EntityManagerFactoryInfo 설정 검사에 응답할 수도 있습니다.
그러나
다른 컴포넌트가 실제 JPA provider에 접근하는 순간(예: createEntityManager 호출),
해당 호출은 background bootstrapping이 완료될 때까지 block됩니다. 특히 Spring Data JPA를
사용하는 경우, 리포지토리에 대해서도 지연 부트스트래핑을 설정해야 합니다.
6.2부터는 비동기 부트스트래핑이 완료될 때까지 기다리면서 컨텍스트 refresh completion 전에
JPA 초기화가 강제됩니다. 이는 완전히 초기화된 데이터베이스 인프라의 가용성을 예측 가능하게 만들고,
ContextRefreshedEvent listener 등의 커스텀 post-initialization 로직을 허용합니다.
이러한 애플리케이션 레벨 데이터베이스 초기화를 @PostConstruct 메서드 등에 넣는 것은 권장되지 않습니다.
이는 Lifecycle.start(해당되는 경우) 또는 ContextRefreshedEvent listener에 두는 것이 더 좋습니다.
EntityManagerFactory 및 EntityManager
EntityManagerFactory인스턴스는 thread-safe이지만,EntityManager인스턴스는 thread-safe가 아닙니다. 주입된 JPAEntityManager는 JPA 명세에서 정의한 대로, 애플리케이션 서버의 JNDI 환경에서 가져온EntityManager처럼 동작합니다. 이는 모든 호출을 현재 트랜잭션EntityManager(있는 경우)에 위임합니다. 그렇지 않으면, 작업당 새로 생성된EntityManager로 fallback하여, 사실상 그 사용을 thread-safe하게 만듭니다.
EntityManagerFactory 또는 EntityManager를 주입하여 Spring 의존성 없이
plain JPA에 대해 코드를 작성하는 것이 가능합니다. PersistenceAnnotationBeanPostProcessor가
활성화된 경우, Spring은 field와 method level 모두에서 @PersistenceUnit 및
@PersistenceContext 어노테이션을 이해할 수 있습니다.
다음 예제는 @PersistenceUnit 어노테이션을 사용하는
plain JPA DAO 구현을 보여줍니다:
1public class ProductDaoImpl implements ProductDao { 2 3 private EntityManagerFactory emf; 4 5 @PersistenceUnit 6 public void setEntityManagerFactory(EntityManagerFactory emf) { 7 this.emf = emf; 8 } 9 10 public Collection loadProductsByCategory(String category) { 11 EntityManager em = this.emf.createEntityManager(); 12 try { 13 Query query = em.createQuery("from Product as p where p.category = ?1"); 14 query.setParameter(1, category); 15 return query.getResultList(); 16 } 17 finally { 18 if (em != null) { 19 em.close(); 20 } 21 } 22 } 23}
1class ProductDaoImpl : ProductDao { 2 3 private lateinit var emf: EntityManagerFactory 4 5 @PersistenceUnit 6 fun setEntityManagerFactory(emf: EntityManagerFactory) { 7 this.emf = emf 8 } 9 10 fun loadProductsByCategory(category: String): Collection<*> { 11 val em = this.emf.createEntityManager() 12 val query = em.createQuery("from Product as p where p.category = ?1") 13 query.setParameter(1, category) 14 return query.resultList 15 } 16}
앞선 DAO는 Spring에 대한 의존성이 없지만 여전히 Spring
애플리케이션 컨텍스트에 잘 맞습니다. 또한 DAO는 어노테이션을 활용하여
기본 EntityManagerFactory의 주입을 요구합니다.
다음 예제 bean 정의가 이를 보여줍니다:
1<beans> 2 3 <!-- bean post-processor for JPA annotations --> 4 <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> 5 6 <bean id="myProductDao" class="product.ProductDaoImpl"/> 7 8</beans>
PersistenceAnnotationBeanPostProcessor를 명시적으로 정의하는 대신,
애플리케이션 컨텍스트 설정에서 Spring context:annotation-config XML element를 사용하는 것을
고려하십시오. 이렇게 하면 어노테이션 기반 설정을 위한 모든 Spring standard
post-processor(CommonAnnotationBeanPostProcessor 등 포함)가 자동으로 등록됩니다.
다음 예제를 고려하십시오:
1<beans> 2 3 <!-- post-processors for all standard config annotations --> 4 <context:annotation-config/> 5 6 <bean id="myProductDao" class="product.ProductDaoImpl"/> 7 8</beans>
이러한 DAO의 주요 문제는 항상 factory를 통해 새 EntityManager를 생성한다는 점입니다.
이를 피하기 위해 factory 대신 트랜잭션 EntityManager(실제 트랜잭션
EntityManager에 대한 공유, thread-safe 프록시이기 때문에 “shared EntityManager”라고도 함)를
주입하도록 요청할 수 있습니다.
다음 예제는 이를 수행하는 방법을 보여줍니다:
1public class ProductDaoImpl implements ProductDao { 2 3 @PersistenceContext 4 private EntityManager em; 5 6 public Collection loadProductsByCategory(String category) { 7 Query query = em.createQuery("from Product as p where p.category = :category"); 8 query.setParameter("category", category); 9 return query.getResultList(); 10 } 11}
1class ProductDaoImpl : ProductDao { 2 3 @PersistenceContext 4 private lateinit var em: EntityManager 5 6 fun loadProductsByCategory(category: String): Collection<*> { 7 val query = em.createQuery("from Product as p where p.category = :category") 8 query.setParameter("category", category) 9 return query.resultList 10 } 11}
@PersistenceContext 어노테이션에는 type이라는 optional attribute가 있으며,
기본값은 PersistenceContextType.TRANSACTION입니다. 이 기본값을 사용하면 공유
EntityManager 프록시를 받을 수 있습니다.
대안인 PersistenceContextType.EXTENDED는 완전히
다른 개념입니다. 이는 소위 extended EntityManager를 생성하는데, 이는 thread-safe가 아니며,
따라서 Spring-managed 싱글톤 bean과 같은 동시에 접근되는 컴포넌트에서 사용되어서는 안 됩니다.
Extended EntityManager 인스턴스는 예를 들어 세션에 존재하는 stateful 컴포넌트에서만 사용되어야 하며,
EntityManager의 라이프사이클은 현재 트랜잭션에 묶이지 않고 완전히 애플리케이션에 달려 있습니다.
Method- 및 field-level Injection
@PersistenceUnit 및 @PersistenceContext와 같이 의존성 주입을 나타내는 어노테이션은
클래스 내부의 field나 method에 적용할 수 있습니다. 따라서 “method-level injection” 및
“field-level injection”이라는 표현이 사용됩니다.
Field-level 어노테이션은 간결하고 사용하기 쉬운 반면, method-level 어노테이션은 주입된 의존성에 대한 추가 처리을 허용합니다. 두 경우 모두 멤버 가시성(public, protected, private)은 중요하지 않습니다.
Class-level 어노테이션은 어떻습니까?
Jakarta EE 플랫폼에서는 의존성 선언을 위해 사용되며 리소스 주입을 위해 사용되지 않습니다.
주입된 EntityManager는 Spring-managed(ongoing 트랜잭션을 인식)입니다.
새 DAO 구현은 EntityManagerFactory 대신 EntityManager의 method-level injection을 사용하지만,
어노테이션 사용으로 인해 bean 정의에는 변경이 필요 없습니다.
이러한 DAO 스타일의 주요 장점은 Java Persistence API에만 의존한다는 점입니다. 어떠한 Spring 클래스도 import할 필요가 없습니다. 또한 JPA 어노테이션이 이해되므로, Spring 컨테이너에 의해 주입이 자동으로 적용됩니다.
이는 비침투성 관점에서 매력적이며, JPA 개발자에게 더 자연스럽게 느껴질 수 있습니다.
@Autowired 기반 DAO 구현(일반적으로 생성자 기반 주입 사용)@PersistenceUnit 및 @PersistenceContext는 method 및 field에만 선언할 수 있습니다.
그렇다면 생성자 및 기타 @Autowired 주입 지점을 통해 JPA 리소스를 제공하는 것은 어떻습니까?
EntityManagerFactory는 대상이 예를 들어 LocalContainerEntityManagerFactoryBean을 통해
bean으로 정의되어 있는 한 생성자 및 @Autowired field/method를 통해 쉽게 주입될 수 있습니다.
주입 지점은 타입 기준으로 original EntityManagerFactory 정의와 그대로 매칭됩니다.
그러나 @PersistenceContext 스타일의 공유 EntityManager reference는
기본적으로 일반 의존성 주입을 위해 사용 가능하지 않습니다. @Autowired에서 요구하는
타입 기반 매칭을 위해 이를 사용 가능하게 만들려면, EntityManagerFactory 정의의
companion으로 SharedEntityManagerBean을 정의하는 것을 고려하십시오:
1<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 2 ... 3</bean> 4 5<bean id="em" class="org.springframework.orm.jpa.support.SharedEntityManagerBean"> 6 <property name="entityManagerFactory" ref="emf"/> 7</bean>
또는 SharedEntityManagerCreator 기반의 @Bean 메서드를 정의할 수도 있습니다:
1@Bean("em") 2public static EntityManager sharedEntityManager(EntityManagerFactory emf) { 3 return SharedEntityManagerCreator.createSharedEntityManager(emf); 4}
여러 persistence unit이 있는 경우, 각 EntityManagerFactory 정의는
해당하는 EntityManager bean 정의와 함께 제공되어야 하며, 이상적으로는
서로 다른 persistence unit을 @Autowired @Qualifier("…")를 통해 구분할 수 있도록
서로 다른 EntityManagerFactory 정의와 매칭되는 qualifier를 가져야 합니다.
Spring의 선언적 트랜잭션 지원에 대한 보다 자세한 내용을 얻으려면, 아직 읽지 않았다면 Declarative Transaction Management를 읽을 것을 강력히 권장합니다.
JPA에 대한 권장 전략은 JPA의 native 트랜잭션 지원을 통한 로컬 트랜잭션입니다.
Spring의 JpaTransactionManager는 JTA 트랜잭션 코디네이터 및 XA-capable 리소스를 요구하지 않고,
어떠한 일반 JDBC 커넥션 풀에 대해서도 로컬 JDBC 트랜잭션에서 알려진 많은 capability
(예: 트랜잭션별 격리 수준 및 리소스 레벨 읽기 전용 최적화)를 제공합니다.
Spring JPA는 또한 등록된 JpaDialect가 underlying JDBC Connection의 retrieval을 지원하는 경우,
구성된 JpaTransactionManager가 동일한 DataSource에 접근하는 JDBC 액세스 코드에
JPA 트랜잭션을 노출하도록 허용합니다. Spring은 EclipseLink 및 Hibernate JPA 구현을 위한
dialect를 제공합니다.
JpaDialect에 대한 자세한 내용은 다음 section을
참조하십시오.
JTA 스타일의 실제 리소스 커넥션 지연 retrieval을 위해, Spring은 target 커넥션 풀에 대한
corresponding DataSource 프록시 클래스를 제공합니다. LazyConnectionDataSourceProxy를
참조하십시오. 이는 데이터베이스를 hit하는 대신 로컬 캐시에서 처리될 수 있는 경우가 많은
JPA 읽기 전용 트랜잭션에 특히 유용합니다.
JpaDialect 및 JpaVendorAdapter 이해하기고급 기능으로서, JpaTransactionManager 및 AbstractEntityManagerFactoryBean의 subclass는
커스텀 JpaDialect를 jpaDialect bean property로 전달할 수 있게 해줍니다.
JpaDialect 구현은 일반적으로 vendor-specific 방식으로 Spring이 지원하는
다음과 같은 advanced feature를 enable할 수 있습니다:
Connection retrieval(JDBC 기반 DAO에 노출하기 위해)PersistenceException을 Spring의 DataAccessException으로 advanced translation이는 특히 special 트랜잭션 semantic 및 advanced 예외 변환에
가치가 있습니다. 기본 구현(DefaultJpaDialect)은 어떠한 special ability도 제공하지 않으며,
앞서 나열한 feature가 필요하다면 적절한 dialect를 지정해야 합니다.
Spring의 full-featured
LocalContainerEntityManagerFactoryBean설정을 위한 보다 광범위한 provider adaptation facility로서,JpaVendorAdapter는JpaDialect의 capability를 다른 provider-specific 기본값과 결합합니다.HibernateJpaVendorAdapter또는EclipseLinkJpaVendorAdapter를 지정하는 것은 각각 Hibernate 또는 EclipseLink를 위한EntityManagerFactory설정을 자동 구성하는 가장 편리한 방법입니다. 이러한 provider adapter는 주로 Spring-driven 트랜잭션 관리(즉,JpaTransactionManager와의 사용)를 위해 설계되었다는 점에 유의하십시오.
JpaDialect 및
JpaVendorAdapter javadoc을 참조하여
operation 및 Spring의 JPA 지원 내에서 어떻게 사용되는지에 대한 자세한 내용을 확인하십시오.
JpaTransactionManager의 대안으로, Spring은 Jakarta EE 환경 또는 Atomikos와 같은
독립 실행형 트랜잭션 코디네이터에서 JTA를 통한 multi-resource 트랜잭션 조정도 허용합니다.
Spring의 JpaTransactionManager 대신 JtaTransactionManager를 선택하는 것 외에는
몇 가지 추가 단계만 필요합니다:
DataSource를 노출합니다.
자세한 내용은 애플리케이션 서버 문서를 참조하십시오. 유사하게, standalone 트랜잭션 코디네이터는
일반적으로 special XA-integrated DataSource variant와 함께 제공됩니다. 마찬가지로 해당 문서를 확인하십시오.EntityManagerFactory 설정은 JTA용으로 구성되어야 합니다.
이는 provider-specific하며, 일반적으로 LocalContainerEntityManagerFactoryBean의
jpaProperties로 지정해야 하는 special property를 통해 이루어집니다. Hibernate의 경우,
이러한 property는 버전별이기까지 합니다. 자세한 내용은 Hibernate 문서를 참조하십시오.HibernateJpaVendorAdapter는 커넥션 release mode와 같이 특정 Spring-oriented 기본값을
강제합니다. 예를 들어, on-close는 Hibernate 5.0에서는 Hibernate의 자체 기본값과 일치하지만
Hibernate 5.1+에서는 더 이상 그렇지 않습니다. JTA 설정의 경우, persistence unit 트랜잭션 타입을
"JTA"로 선언해야 합니다. 또는 Hibernate 5.2의 hibernate.connection.handling_mode property를
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT로 설정하여 Hibernate의 자체 기본값을 복원하십시오.
관련 note는 Spurious Application Server Warnings with Hibernate를
참조하십시오.EntityManagerFactory를 얻는 것을 고려하십시오(즉, 로컬로 선언된
LocalContainerEntityManagerFactoryBean 대신 JNDI lookup을 통해). 서버 제공
EntityManagerFactory는 서버 설정에서 special 정의를 필요로 할 수 있습니다
(배포를 덜 portable하게 만듦). 그러나 서버의 JTA 환경을 위해 설정됩니다.HibernateTransactionManager와 결합된 native LocalSessionFactoryBean 설정은
@PersistenceContext 및 기타 JPA 액세스 코드와의 상호 작용을 허용합니다. Hibernate
SessionFactory는 이제 JPA의 EntityManagerFactory 인터페이스를 native하게 구현하며,
Hibernate Session handle은 native하게 JPA EntityManager입니다.
Spring의 JPA 지원 facility는 native Hibernate session을 자동으로 감지합니다.
따라서 이러한 native Hibernate 설정은 많은 시나리오에서 표준 JPA
LocalContainerEntityManagerFactoryBean 및 JpaTransactionManager 조합의 대체로 사용될 수 있으며,
동일한 로컬 트랜잭션 내에서 SessionFactory.getCurrentSession()
(및 HibernateTemplate)과 @PersistenceContext EntityManager 간의 상호 작용을 허용합니다.
이러한 설정은 또한 JPA 부트스트랩 contract에 의해 제한되지 않기 때문에 더 강력한 Hibernate 통합 및 더 많은 설정 유연성을 제공합니다.
이러한 시나리오에서는 HibernateJpaVendorAdapter 설정이 필요하지 않습니다.
Spring의 native Hibernate 설정은 커스텀 Hibernate Integrator 설정, Hibernate 5.3 bean 컨테이너 통합,
읽기 전용 트랜잭션에 대한 보다 강력한 최적화 등 더 많은 feature를 제공하기 때문입니다.
마지막으로, native Hibernate 설정은 LocalSessionFactoryBuilder를 통해서도 표현할 수 있으며,
@Bean 스타일 설정과 원활하게 통합됩니다(FactoryBean이 필요 없음).
LocalSessionFactoryBean및LocalSessionFactoryBuilder는 JPALocalContainerEntityManagerFactoryBean과 마찬가지로 background bootstrapping을 지원합니다. 소개는 Background Bootstrapping을 참조하십시오.LocalSessionFactoryBean에서는bootstrapExecutorproperty를 통해 이를 사용할 수 있습니다. 프로그래밍 방식LocalSessionFactoryBuilder에서는 오버로드된buildSessionFactory메서드가 bootstrap executor argument를 받습니다.
Hibernate
Marshalling XML by Using Object-XML Mappers