사용자 정의 리포지토리 구현
Spring Data JPA 에서 커스텀 기능을 개발하고 싶은 경우 ex) pure JPA 나 JDBCTmpl 쓰고 싶을 때
- 깨끗한 인터페이스를 하나 만들고 그를 상속받는 클래스를 만들어, 클래스에서 커스텀한 기능을 만든다.
- @PersistenceContext EntityManager (pureJPA)
- @Autowired SqlSession (jdbcTmpl)
-
Spring Data JPA Repository 의 extends 에 “, (인터페이스)” 를 추가한다.
- Spring Data JPA 가 규칙에 의해 자동으로 메서드를 연결해주어 Spring Data JPA 에 구현된 메서드처럼 사용이 가능하다
(추가1) 커스텀 클래스명은 (Spring Data Jpa Repository 이름) + Impl 의 규칙을 지켜야 한다. (커스텀 인터페이스명은 상관 X) ex) MemberRepository -> MemberRepositoryImpl 만약 위 규칙을 바꾸고 싶다면 JavaConfig 에서 다음과 같이 바꿀 수 있다 @EnableJpaRepositories(basePackages = “패키지경로”, repositoryImplementationPostfix = “Impl22”)
(추가2) Spring Data JPA 를 사용하지 않고 pureJPA 나 JDBCTmpl, 혹은 QueryDSL 을 써서 Repository 를 별도 Bean 으로 구성하여 사용하는것도 실무에서 많이 쓰인다.
(실무노하우) “핵심 비즈니스 로직쿼리”와 “프론트에 데이터를 뿌려주기 위한 용도의 쿼리” 는 Repository 를 분리해서 개발하는게 좋다. 핵심 비즈니스 로직쿼리 객체의 복잡도를 낮춰주기도 하고, 애시당초 둘은 개발수정 라이프사이클이 다르다.
Auditing
엔티티 등록자, 등록일시, 수정자, 수정일시 추적을 위한 기능
@MappedSuperclass 엔티티 간의 공통컬럼에 대해서 하나의 클래스만 만들어서 공유하고 싶을 경우, 엔티티 클래스 생성 후 다른 엔티티에 extends 하면 된다. 그럴 경우 공통컬럼을 가지고 있는 부모클래스(엔티티)에 위의 @MappedSuperclass 어노테이션을 추가해야한다.
@Column(updatable = false) : 컬럼에 대해서 수정불가 처리할 수 있다
pure JPA 주요 이벤트 어노테이션 @PrePersist, @PostPersits, @PreUpdate, @PostUpdate @PrePersist : pureJPA 에서 메서드에 해당 어노테이션을 붙이면 em.persist(insert) 전에 해당 메서드가 실행된다. (예제에서는 해당 기능을 통해 regDtt 와 modDtt 를 현재시간으로 초기화했다) @preUpdate : dirtyChecking 으로 인해 (update) 가 실행되기 전에 해당 어노테이션이 붙은 메서드가 실행된다
Web 확장 - 도메인 클래스 컨버터
도메인 클래스 컨버터
@GetMapping(“/members/{id}”) public void getMember(@PathVariable(name = “id”) Member member) { … } 알아서 PK 로 검색함
페이징과 정렬
@GetMapping(“/members”)
public Page
@GeneratedValue 의 값 생성 타이밍 em.persist 이후 생성. 그 전까지 PK 값은 null 임
Spring Data JPA 의 구현체(class) 인 SimpleJpaRepository 의 save 에 isNew 라는 이 객체가 새로운 객체인지 판단하는 로직이 있음 PK 가 Object 이면 null, primitive 이면 0 일때 new 객체로 판단한다.
그러나 구현방법에 따라 PK 가 null 이 아니지만 새로운 객체인 경우도 있을 것이다. 그런 경우엔 implements Persistable
네이티브 쿼리
가급적 네이티브 쿼리는 사용하지 않는게 좋음, 정말 어쩔수 없을 때 사용
@Query(value = “select * from Member where username = ?”, nativeQuery = true)
List
보통은 (쓴다면) 프론트에 데이터 제공을 위해 DTO 에 매핑하는 무거운 쿼리에 사용한다. 되도록 NativeQuery 말고 JDBCTmpl 이나 MyBatis 를 권장한다고 한다
쌩자 NativeQuery 는 JPA 본 기능이랑 충돌나는 경우 (특히 정렬,페이징) 가 있다고 하는데 이를 피하기 위해서 Projection 이랑 엮어서 쓰면 그나마 낫다고 한다
참고
- https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-JPA-%EC%8B%A4%EC%A0%84