https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-jpa
ㅁ 스프링 데이터 JPA
* JpaRepository
- @EnableJpaRepositories를 설정해야 , JpaRepository를 extends 한 인터페이스 repository가 자동으로 등록됨
> 현재는 부트가 자동으로 해줘서 설정 안해도 됨
- @Repository를 다는건 중복 ( 이미 JpaRepository 구현체인 SimpleRepository가 @Repository를 가지고 있음 )
> 중복으로 달아서 SQLException, JPA 관련 오류를 DataAccessException으로 변환하는 상황도 있긴 함
- EntityManager.persiste() : Transient (새로 만들어짐, 아무도 이 객체에 대해 모름 , 테이블에도 없음 ) => Persistent (PersistentContext가 Managing을 함, 캐싱 등 )
EntityManager.merge() : Detached (한번이라도 Persistent 했던 객체 ) => Persistent
>> 객체에 id가 있으면 merge(Detached 상태 ), 없으면 (null) persist (Transient 상태)
- save 하고 나면, 리턴받는 값이 Persistent하기 때문에 이것을 사용하는 것이 좋다.
> merge가 일어난거면 persist되는 객체가 아니게되기 때문에 알아내기 어려움
* JPA 쿼리 메소드
- JPQL
> @NamedQuery(name="Post.findByTitle",query="SELECT p FROM Post AS p WHERE p.title=?1")
> Entity 위에 설정
>> Entity위가 지저분해짐
>> nativeQuery도 마찬가지
- Repository 에 @Query 후 쿼리 작성
@Query("SELECT p FROM Post AS p WHERE p.title=?1")
List<Post> findByTitle(String title);
>> nativeQuery= true 추가하여 네이티브 쿼리로도 설정 가능
* Sort
- alias나 프로퍼티만 사용 가능 (ex ) Sort.by("title"))
- 함수를 쓰고 싶으면? JpaSort.unsafe("LENGTH(title)) 로 넘겨준다
* Named Parameter
- @Param , #{#entityName} (SpEL)
@Query("SELECT p FROM #{#entityName} AS p WHERE p.title=:title")
List<Post> findByTitle(@Param("title") String keyword, Sort sort);
* Update 쿼리
- Persistent 상태로 상태 변화시키면 자동으로 update 진행됨
- 일부로 update 실행하고 싶다면? @Modifying , @Query 사용
Modifying(clearAutomatically = true)
@Query("Update Post p Set p.title= ?1 WHERE p.id = ?2")
int updateTitle(String hibernate, Long id);
- @Modifying(clearAutomatically = true) 를 통해 쿼리 실행시 PersistentContext 객체를 클리어 해줌
- flush랑 clear를 사용하는것보다는 어플리케이션 코드 (persitent 상태 관리 ) 를 통해 update, delete 하는게 훨씬 좋음
* EntityGraph
- @ManyToOne 등 연관관계 설정하는 곳에 fetch= FecthType.LAZY 등으로 넣을 수 있음
- @NamedEntityGraph(name="Comment.post"
attributeNodes = @NamedAttributeNode("post"))
- Fetch : 설정한 엔티티 애트리뷰트는 EAGER 나머지는 LAZY
- 각각의 쿼리 메소드마다 다른 패치 전략으로 읽어오도록 설정 가능하다
* Projection
- DB에서 일부만 가져올 수 있게 하는 기능
- 클로즈드 : 필요한 것만 가져옴 (성능 최적화 가능 )
- 오픈 : 일단 다 가져와서 거기서 조합함 (성능 최적화 못함)
- default 메소드를 써서 만들수 있음 (자바 8부터)
* specifications
- QueryDSL의 Predicate와 비슷
- QueryDSL과 Specifications를 쓰면 Repository에 많은 쿼리를 추가하지않아도 조건절 등으로 가져올 수 있음
* Query By Example
- Probe : 도메인 객체
- 어떤 특정 조건을 가진 예제객체를 가지고 이것과 비슷한 조건을 찾음
- 조건 여러개를 할 수 없음
- 필드(컬럼) 이름이 들어가며, 리팩토링하기 힘듬
- 계륵같은 존재.. 잘 안쓰는것
- 유연하면서 테스트할수 있고, 확장성 있는건 QueryDSL, Specification을 쓰는게 좋음
* 트랜잭션
- 스프링 프레임워크 제공 기능
- @Transactional
> 런타임익셉션 및 에러가 발생할 경우 롤백 진행 (not checked exception)
> timeout 설정 가능
> JpaTransactionManager
> Isolation : transaction이 DB에 접근했을때, 이것을 어떻게 처리할 것인지 나타냄 (기본값은 default : DB 설정을 따름 )
>> dirty read : commit 되지않은것도 읽음
> readonly 성능 최적화와 관련 있음 , 데이터 변경 작업 없으면 true로 주기
> Propagation : 트랙잭션을 어떻게 전파 시킬 것인지, 트랙잭션 메소드에서 다른걸 호출할 경우 (nested transaction) , 그것을 어떻게 처리 할 것인가
- flush mode : 데이터를 언제 싱크를 맞출지
> readOnly 로 가져오면 dirty checking를 안하고 flush mode가 never로 세팅되기때문에 성능이 좋아짐
* Auditing
- 엔티티의 변경 시점에 언제, 누가 변경했는지에 대한 정보를 기록하는 기능 (createdBy, createdDate 등..)
- @EnableJpaAuditing을 어플리케이션에 설정
> entity에도 리스너 추가 (@EntityListeners(AuditingEntityListener.class) )
- @Service로 등록하면 빈은 앞에 글자가 소문자로 등록됨
- 스프링 시큐리티도 설치해야함 (Account를 호출하여 입력하기 위해서는)
- @Service는 @DataJpaTest에 bean으로 등록 안됨
* JPA의 라이프사이클 이벤트
- Entity가 변화가 있을때 이벤트를 발생 시킴
- Auditing을 설정 안해도, PrePersist() 등을 통해 생성될때 시간을 입력하는것 등을 할 수 있다. (@PrePersist)
- enum 객체가 있을때, @Enumerated(value= EnumType.STRING ) 으로 매핑하기
> 순서로 하면 안됨 (기본값이 순서) - 리팩토링이 어려움
'Spring' 카테고리의 다른 글
[Spring] 스프링 웹 MVC - 2 (0) | 2021.07.28 |
---|---|
[Spring] 스프링 웹 MVC - 1 (0) | 2021.07.27 |
[Spring] 스프링 데이터 JPA - 3 (0) | 2021.07.25 |
[Spring] 스프링 데이터 JPA - 2 (0) | 2021.07.23 |
[Spring] 스프링 데이터 JPA - 1 (0) | 2021.07.22 |