on
[Spring] Spring Data JPA - (1)
[Spring] Spring Data JPA - (1)
기본이 되는 Annotation
@Entity : 현 클래스를 테이블과 매핑함을 선언
@Table : 매핑할 테이블 정보를 선언
@Id : 엔티티 클래스의 필드를 테이블의 기본 키에 매핑
@Column : 필드를 컬럼에 매핑. name 속성을 사용해 어느 컬럼과 매핑할 것인지 명시할 수 있다.
기본 개념 및 설정
EntityManager : Entity를 관리하는 역할
: Entity를 관리하는 역할 Transaction : 작업 단위. 오류났을 때는 rollback, 정상적으로 수행되었을 때는 commit.
JPA는 쿼리를 한 방에 날리기 때문에 Transaction의 단위가 작게 잡아야 안정성이 커진다.
: 작업 단위. 오류났을 때는 rollback, 정상적으로 수행되었을 때는 commit. JPA는 쿼리를 한 방에 날리기 때문에 Transaction의 단위가 작게 잡아야 안정성이 커진다. Persistence Context : EntityManager가 초기화 및 종료되지 않는 한 Entity를 영구히 저장하는 환경 비영속 : @Entity를 갖는 instance를 막 생성했을 때는 Persistence Context에서 관리하지 않는다. EntityManager의 persist 메소드를 이용해 영속 상태로 변경가능하다. 영속 : 주의할 점은 id필드가 없을 경우 예외를 뱉어낸다. 그 이유는 id를 가지고 데이터를 관리를 하기 때문이다.
이로 인해 얻는 장점 1차 캐시(find메소드 호출 시 캐시된 데이터를 먼저 찾음) 동일성 보장(JPA를 통해 불러온 데이터는 모두 캐시 데이터에 저장되기 때문에 같은 ID를 가진 데이터는 같은 데이터) Transaction 쓰기 지연(Transaction 시작 시 모두 쓰기 지연 저장소에 저장되고 commit 수행 시 모두 실행) 변경 감지(데이터를 저장하기 전 저장된 데이터가 있는지 확인) 지연 로딩 준영속 : 영속 상태였으나 Persistence Context에서 분리되어 더 이상 관리하지 않는 데이터가 된 상태.
detach 메소드를 통해서 해당 상태로 변경 가능하다. 이 상태는 관리는 되지 않지만 정상적인 데이터를 가지고 있다.
주로 Persistenc Context 자체가 초기화 혹은 종료되면 일어나고 이 때는 Context 내부의 모든 데이터가 준영속 상태가 된다. merge를 통해 다시 영속이 가능하다. 삭제 : Entity를 Persistence Context와 DB 양쪽에서 모두 삭제한다. (remove 메소드)
: EntityManager가 초기화 및 종료되지 않는 한 Entity를 영구히 저장하는 환경
* flush 메소드 : Persistence Context의 변경 내용을 DB에 반영한다. 동작 순서는 변경 감지 -> 생성된 쿼리를 쓰기 지연 저장소에 등록 -> commit 후 저장되어 있던 쿼리를 모두 수행
* close 메소드 : Persistence Context 종료
EntityManagerFactory
EntityManager는 여러 Thread가 동시에 접근하면 동시성 문제가 발생하므로 Thread 간에 절대 공유하면 안 된다. (동시성 -> 데이터 수정 도중 다른 Thread가 미리 수정하는 경우)
그래서 하나를 공유하면 안 되고 상황에 따라서 계속해서 만들어줘야한다. 이러한 EntityManager를 만드는 것이 EntityManagerFactory이다. 이건 여러 Thread가 동시에 접근해도 안전하다. 이유는 EntityManager를 만들기만 하는 클래스이다.
EntityManager는 여러 Thread가 동시에 접근하면 동시성 문제가 발생하므로 Thread 간에 절대 공유하면 안 된다. (동시성 -> 데이터 수정 도중 다른 Thread가 미리 수정하는 경우) 그래서 하나를 공유하면 안 되고 상황에 따라서 계속해서 만들어줘야한다. 이러한 EntityManager를 만드는 것이 EntityManagerFactory이다. 이건 여러 Thread가 동시에 접근해도 안전하다. 이유는 EntityManager를 만들기만 하는 클래스이다. JpaVendorAdapter : EntityManagerFactory에 vendor-speicfic behavior(좀 더 공부를 할 내용)를 허가하는 것.
: EntityManagerFactory에 vendor-speicfic behavior(좀 더 공부를 할 내용)를 허가하는 것. JpaProperties : JPA 특징을 관리할 수 있다.
: JPA 특징을 관리할 수 있다. PlatformTransactionManager
모든 Spring의 트랜잭션 기능과 코드를 이 인터페이스를 통해서 Low-level의 트랜잭션 서비스를 이용한다. 트랜잭션 경계를 지정하는데 사용한다. 그 중 JpaTransactionManager를 이용해서 JPA에서 트랜잭션이 가능하게끔 한다.
package com.example.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import java.util.Properties; @Configuration @EnableJpaRepositories(basePackages = "com.example.entity") @PropertySource("classpath:/application.properties") public class Appconfig { @Autowired DataSource dataSource; @Bean public EntityManagerFactory entityManagerFactory() { HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); hibernateJpaVendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); // factory bean을 생성 factory.setJpaVendorAdapter(hibernateJpaVendorAdapter); factory.setJpaProperties(properties()); factory.setPackagesToScan("com.example.entity"); factory.setDataSource(dataSource); factory.afterPropertiesSet(); return factory.getObject(); } // transactionManager @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory((entityManagerFactory())); // 트랜잭션 매니져에 EntityManagerFactory를 set return txManager; } private Properties properties() { Properties properties = new Properties(); properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect"); // mysql 방언 사용 properties.put("hibernate.show_sql", "true"); // sql 보이기 properties.put("hibernate.hbm2dll.auto", "validation"); // ddl을 db로 검증시 객체 구성과 스키마가 다르면 예외 발생 return properties; } }
from http://jollypyun.tistory.com/93 by ccl(A) rewrite - 2021-12-23 16:27:24