5.7. 거래 성
기본적으로 저장소 인스턴스의 CRUD 메소드는 트랜잭션입니다. 읽기 조작의 경우 트랜잭션 구성 readOnly
플래그가로 설정됩니다 true
. 다른 모든 @Transactional
트랜잭션은 기본 트랜잭션 구성이 적용되도록 일반 으로 구성됩니다. 자세한 내용은 JavaDoc of를 참조하십시오 SimpleJpaRepository
. 저장소에 선언 된 메소드 중 하나에 대한 트랜잭션 구성을 조정해야하는 경우 다음과 같이 저장소 인터페이스에서 메소드를 다시 선언하십시오.
public interface UserRepository extends CrudRepository<User, Long> {
@Override
@Transactional(timeout = 10)
public List<User> findAll();
// Further query method declarations
}
그렇게하면 findAll()
메소드가 readOnly
플래그 없이 10 초의 시간 종료로 실행됩니다 .
트랜잭션 동작을 변경하는 또 다른 방법은 일반적으로 둘 이상의 저장소를 포괄하는 파사드 또는 서비스 구현을 사용하는 것입니다. CRUD 이외의 조작에 대한 트랜잭션 경계를 정의하는 것이 목적입니다. 다음 예제는 하나 이상의 저장소에 이러한 외관을 사용하는 방법을 보여줍니다.
@Service
class UserManagementImpl implements UserManagement {
private final UserRepository userRepository;
private final RoleRepository roleRepository;
@Autowired
public UserManagementImpl(UserRepository userRepository,
RoleRepository roleRepository) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
}
@Transactional
public void addRoleToAllUsers(String roleName) {
Role role = roleRepository.findByName(roleName);
for (User user : userRepository.findAll()) {
user.addRole(role);
userRepository.save(user);
}
}
이 예 addRoleToAllUsers(…)
에서는 트랜잭션 내에서 호출이 실행되도록합니다 (기존 트랜잭션에 참여하거나 이미 실행중인 트랜잭션이없는 경우 새로 작성). 그러면 외부 트랜잭션 구성이 사용 된 실제 트랜잭션 구성을 결정하므로 리포지토리의 트랜잭션 구성은 무시됩니다. 주석 기반의 파사드 구성을 <tx:annotation-driven />
사용 하려면 활성화 하거나 @EnableTransactionManagement
명시 적으로 사용해야 합니다. 이 예에서는 구성 요소 검색을 사용한다고 가정합니다.
5.7.1. 트랜잭션 쿼리 방법
쿼리 메소드를 트랜잭션 방식으로 @Transactional
만들려면 다음 예제와 같이 정의한 저장소 인터페이스에서 사용하십시오.
@Transactional(readOnly = true)
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastname(String lastname);
@Modifying
@Transactional
@Query("delete from User u where u.active = false")
void deleteInactiveUsers();
}
대부분의 쿼리 메소드는 데이터 만 읽으므로 일반적으로 readOnly
플래그를로 설정하려고 true
합니다. 이와 달리 주석 deleteInactiveUsers()
을 사용 @Modifying
하고 트랜잭션 구성을 재정의합니다. 따라서이 메소드는 readOnly
플래그가로 설정된 상태로 실행 됩니다 false
.
읽기 전용 쿼리에 트랜잭션을 사용하고 |
5.8. 잠금
사용할 잠금 모드를 지정하기 @Lock
위해 다음 예제와 같이 쿼리 메소드에 주석을 사용할 수 있습니다 .
interface UserRepository extends Repository<User, Long> {
// Plain query method
@Lock(LockModeType.READ)
List<User> findByLastname(String lastname);
}
이 방법 선언은 쿼리가 장착 될 트리거되는 원인 LockModeType
의 READ
. @Lock
다음 예제와 같이 저장소 인터페이스에서 CRUD 메소드를 다시 선언하고 주석을 추가하여 CRUD 메소드에 대한 잠금을 정의 할 수도 있습니다 .
interface UserRepository extends Repository<User, Long> {
// Redeclaration of a CRUD method
@Lock(LockModeType.READ);
List<User> findAll();
}
5.9. 감사
5.9.1. 기초
Spring Data는 엔티티를 생성 또는 변경 한 사람과 변경시기를 투명하게 추적 할 수있는 정교한 지원을 제공합니다. 이 기능을 활용하려면 엔티티 클래스에 주석을 사용하거나 인터페이스를 구현하여 정의 할 수있는 감사 메타 데이터를 갖추어야합니다.
주석 기반 감사 메타 데이터
우리는 제공 @CreatedBy
및 @LastModifiedBy
만들거나뿐만 아니라 개체를 수정 한 사용자 포착 @CreatedDate
하고 @LastModifiedDate
변화가 일어 났을 때 캡처합니다.
class Customer {
@CreatedBy
private User user;
@CreatedDate
private DateTime createdDate;
// … further properties omitted
}
보시다시피 캡처하려는 정보에 따라 주석을 선택적으로 적용 할 수 있습니다. 변경 시점을 캡처하는 주석은 Joda-Time DateTime
,, legacy Java Date
및 Calendar
, JDK8 날짜 및 시간 유형 및 long
/ 또는 속성에서 사용할 수 있습니다 Long
.
인터페이스 기반 감사 메타 데이터
주석을 사용하여 감사 메타 데이터를 정의하지 않으려는 경우 도메인 클래스가 Auditable
인터페이스를 구현하도록 할 수 있습니다. 모든 감사 속성에 대한 세터 메소드를 제공합니다.
AbstractAuditable
인터페이스 메소드를 수동으로 구현할 필요가 없도록 확장 할 수 있는 편리한 기본 클래스도 있습니다. 그렇게하면 도메인 클래스와 스프링 데이터의 결합이 증가하여 피하고 싶을 수도 있습니다. 일반적으로 감사 메타 데이터를 정의하는 주석 기반 방식은 덜 침습적이고 유연하기 때문에 선호됩니다.
AuditorAware
혹시 사용 중 @CreatedBy
또는 @LastModifiedBy
감사 인프라는 어떻게 든 현재 주 인식 될 필요가있다. 이를 위해 AuditorAware<T>
애플리케이션과 상호 작용하는 현재 사용자 또는 시스템이 누구인지 인프라에 알리기 위해 구현해야하는 SPI 인터페이스를 제공합니다 . 제네릭 형식 T
은 속성에 주석이 @CreatedBy
있거나 필요한 형식을 정의 @LastModifiedBy
합니다.
다음 예제는 Spring Security의 Authentication
객체 를 사용하는 인터페이스의 구현을 보여줍니다 .
class SpringSecurityAuditorAware implements AuditorAware<User> {
public Optional<User> getCurrentAuditor() {
return Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(User.class::cast);
}
}
구현 Authentication
은 Spring Security가 제공 하는 객체에 액세스하고 구현 UserDetails
에서 생성 한 커스텀 인스턴스를 찾습니다 UserDetailsService
. 여기서는 UserDetails
구현을 통해 도메인 사용자를 노출하고 있지만 Authentication
찾은 것을 기반으로 어디에서나 찾을 수 있다고 가정합니다. : 레벨 오프셋 : -1
5.9.2. JPA 감사
일반 감사 구성
Spring Data JPA는 감사 정보 캡처를 트리거하는 데 사용할 수있는 엔티티 리스너와 함께 제공됩니다. 먼저 다음 예제와 같이 파일 AuditingEntityListener
내부의 지속성 컨텍스트에있는 모든 엔티티에 사용되도록를 등록해야합니다 orm.xml
.
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="….data.jpa.domain.support.AuditingEntityListener" />
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
다음과 같이 주석 AuditingEntityListener
을 사용하여 엔터티별로 활성화 할 수도 있습니다 @EntityListeners
.
@Entity
@EntityListeners(AuditingEntityListener.class)
public class MyEntity {
}
감사 기능은 spring-aspects.jar 클래스 경로에 있어야 합니다. |
로 orm.xml
적절히 수정 spring-aspects.jar
클래스 패스에, 감사 기능을 활성화하면 스프링 데이터 JPA의 추가의 문제입니다 auditing
다음과 같이 구성에 네임 스페이스 요소를 :
<jpa:auditing auditor-aware-ref="yourAuditorAwareBean" />
Spring Data JPA 1.5부터 주석으로 구성 클래스에 주석을 달아 감사를 활성화 할 수 있습니다 @EnableJpaAuditing
. 여전히 orm.xml
파일을 수정 spring-aspects.jar
하고 클래스 경로에 있어야합니다 . 다음 예제는 @EnableJpaAuditing
주석 을 사용하는 방법을 보여줍니다 .
@Configuration
@EnableJpaAuditing
class Config {
@Bean
public AuditorAware<AuditableUser> auditorProvider() {
return new AuditorAwareImpl();
}
}
이 유형의 콩 노출되면 AuditorAware
받는 사람을 ApplicationContext
, 감사 인프라는 자동으로 수정 해 현재 사용자가 도메인 유형을 설정할 수를 결정하는 데 사용합니다. 에 여러 구현을 등록한 경우 ApplicationContext
의 auditorAwareRef
속성을 명시 적으로 설정하여 사용할 구현 을 선택할 수 있습니다 @EnableJpaAuditing
.
5.10. 기타 고려 사항
5.10.1. JpaContext
사용자 정의 구현에서 사용
여러 EntityManager
인스턴스 및 사용자 정의 저장소 구현EntityManager
으로 작업하는 경우 저장소 구현 클래스에 올바른 항목을 연결해야합니다 . 명시 적으로 이름을 지정하면됩니다 EntityManager
에서 @PersistenceContext
(가) 경우, 주석 또는 EntityManager
이다 @Autowired
사용하여 @Qualifier
.
Spring Data JPA 1.9부터 Spring Data JPA에는 애플리케이션 의 인스턴스 중 하나만 관리한다고 가정하고 관리 도메인 별 클래스 JpaContext
를 얻을 수 있는 클래스가 포함되어 있습니다 . 다음 예제는 사용자 정의 저장소에서 사용하는 방법을 보여줍니다 .EntityManager
EntityManager
JpaContext
JpaContext
사용자 정의 저장소 구현에서 사용class UserRepositoryImpl implements UserRepositoryCustom {
private final EntityManager em;
@Autowired
public UserRepositoryImpl(JpaContext context) {
this.em = context.getEntityManagerByManagedType(User.class);
}
…
}
이 접근 방식의 장점은 도메인 유형이 다른 지속성 단위에 할당 된 경우 저장소를 터치하여 지속성 단위에 대한 참조를 변경하지 않아도된다는 것입니다.
5.10.2. 지속성 단위 병합
Spring은 다중 지속성 단위를 지원합니다. 그러나 때로는 응용 프로그램을 모듈화하고 이러한 모듈이 모두 단일 지속성 단위 내에서 실행되도록해야 할 수도 있습니다. 이 동작을 가능하게하기 위해 Spring Data JPA는 PersistenceUnitManager
다음 예제와 같이 이름에 따라 지속성 단위를 자동으로 병합 하는 구현을 제공합니다 .
<bean class="….LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager">
<bean class="….MergingPersistenceUnitManager" />
</property>
</bean>
@Entity 클래스 및 JPA 매핑 파일에 대한 클래스 경로 검색
일반 JPA 설정에서는 모든 어노테이션 맵핑 엔티티 클래스가에 나열되어야 orm.xml
합니다. XML 매핑 파일에도 동일하게 적용됩니다. Spring Data JPA는 ClasspathScanningPersistenceUnitPostProcessor
기본 패키지를 구성하고 선택적으로 매핑 파일 이름 패턴을 취하는를 제공합니다 . 그런 다음 @Entity
또는로 주석이 달린 클래스에 대해 주어진 패키지를 스캔하고 @MappedSuperclass
파일 이름 패턴과 일치하는 구성 파일을로드 한 다음 JPA 구성으로 전달합니다. 포스트 프로세서는 다음과 같이 구성해야합니다.
<bean class="….LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitPostProcessors">
<list>
<bean class="org.springframework.data.jpa.support.ClasspathScanningPersistenceUnitPostProcessor">
<constructor-arg value="com.acme.domain" />
<property name="mappingFileNamePattern" value="**/*Mapping.xml" />
</bean>
</list>
</property>
</bean>
Spring 3.1부터 LocalContainerEntityManagerFactoryBean 엔티티 클래스에 대한 클래스 경로 스캐닝을 가능하게 하기 위해 스캔 할 패키지를 직접 구성 할 수 있습니다 . 자세한 내용은 JavaDoc 을 참조하십시오. |
5.10.3. CDI 통합
저장소 인터페이스의 인스턴스는 일반적으로 스프링 데이터로 작업 할 때 스프링이 가장 자연스러운 컨테이너 인 컨테이너에 의해 작성됩니다. Spring은 저장소 인스턴스 작성에 설명 된대로 Bean 인스턴스 작성을위한 정교한 지원을 제공합니다 . 버전 1.1.0부터 Spring Data JPA는 CDI 환경에서 저장소 추상화를 사용할 수있는 사용자 정의 CDI 확장이 제공됩니다. 확장은 JAR의 일부입니다. 이를 활성화하려면 클래스 경로에 Spring Data JPA JAR을 포함 시키십시오.
다음 예와 같이 EntityManagerFactory
and에 대한 CDI 생산자를 구현하여 인프라를 설정할 수 있습니다 EntityManager
.
class EntityManagerFactoryProducer {
@Produces
@ApplicationScoped
public EntityManagerFactory createEntityManagerFactory() {
return Persistence.createEntityManagerFactory("my-presistence-unit");
}
public void close(@Disposes EntityManagerFactory entityManagerFactory) {
entityManagerFactory.close();
}
@Produces
@RequestScoped
public EntityManager createEntityManager(EntityManagerFactory entityManagerFactory) {
return entityManagerFactory.createEntityManager();
}
public void close(@Disposes EntityManager entityManager) {
entityManager.close();
}
}
필요한 설정은 JavaEE 환경에 따라 달라질 수 있습니다. EntityManager
다음과 같이 a를 CDI Bean으로 다시 선언하기 만하면 됩니다.
class CdiConfig {
@Produces
@RequestScoped
@PersistenceContext
public EntityManager entityManager;
}
이전 예제에서 컨테이너는 JPA EntityManagers
자체 를 작성할 수 있어야 합니다. 모든 구성은 JPA EntityManager
를 CDI Bean으로 다시 내보내는 것 입니다.
Spring Data JPA CDI 확장은 사용 가능한 모든 EntityManager
인스턴스를 CDI Bean으로 선택하고 컨테이너가 저장소 유형의 Bean을 요청할 때마다 Spring Data 저장소의 프록시를 작성합니다. 따라서 스프링 데이터 저장소의 인스턴스를 얻는 것은 @Injected
다음 예제와 같이 속성 을 선언하는 문제입니다 .
class RepositoryClient {
@Inject
PersonRepository repository;
public void businessMethod() {
List<Person> people = repository.findAll();
}
}
Spring Data JPA - Reference DocumentationOliver Gierke,Thomas Darimont,Christoph Strobl,Mark Paluch,Jay Bryant
version 2.3.1.RELEASE,2020-06-10 2.3.1.RELEASE © 2008-2019 The original authors. Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically. |
출처 : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
'IT > Spring-Data-JPA' 카테고리의 다른 글
스프링 데이터 JPA #부록 (0) | 2020.06.19 |
---|---|
스프링 데이터 JPA #Reference:프로시저 (0) | 2020.06.19 |
스프링 데이터 JPA #Reference:쿼리 (0) | 2020.06.19 |
스프링 데이터 JPA #Reference:지속 엔티티 (0) | 2020.06.19 |
스프링 데이터 JPA #Intro:레포지터리 작업 (4) (0) | 2020.06.19 |