네이티브 쿼리
2022. 7. 23. 16:50
JPA/JPA-Spring Data
가급적 네이티브 쿼리는 사용하지 않는게 좋음, 정말 어쩔 수 없을 때 사용 최근에 나온 궁극의 방법 스프링 데이터 Projections 활용 스프링 데이터 JPA 기반 네이티브 쿼리 페이징 지원 반환 타입 Object[] Tuple DTO(스프링 데이터 인터페이스 Projections 지원) 제약 Sort 파라미터를 통한 정렬이 정상 동작하지 않을 수 있음(믿지 말고 직접 처리) JPQL처럼 애플리케이션 로딩 시점에 문법 확인 불가 동적 쿼리 불가 JPA 네이티브 SQL 지원 public interface MemberRepository extends JpaRepository { @Query(value = "select * from member where username = ?", nativeQuery =..
Projections
2022. 7. 23. 16:24
JPA/JPA-Spring Data
엔티티 대신에 DTO를 편리하게 조회할 때 사용 전체 엔티티가 아니라 만약 회원 이름만 딱 조회하고 싶으면? public interface UsernameOnly { String getUsername(); } 조회할 엔티티의 필드를 getter 형식으로 지정하면 해당 필드만 선택해서 조회(Projection) public interface MemberRepository ... { List findProjectionsByUsername(String username); } 메서드 이름은 자유, 반환 타입으로 인지 @Test public void projections() throws Exception { //given Team teamA = new Team("teamA"); em.persist(teamA); ..
새로운 엔티티를 구별하는 방법
2022. 7. 23. 04:35
JPA/JPA-Spring Data
새로운 엔티티를 판단하는 기본 전략 식별자가 객체일 때 null 로 판단 식별자가 자바 기본 타입일 때 0 으로 판단 Persistable 인터페이스를 구현해서 판단 로직 변경 가능 package org.springframework.data.domain; public interface Persistable { ID getId(); boolean isNew(); } 참고: JPA 식별자 생성 전략이 @GenerateValue 면 save() 호출 시점에 식별자가 없으므로 새로운 엔티티로 인식해서 정상 동작한다. 그런데 JPA 식별자 생성 전략이 @Id 만 사용해서 직접 할당이면 이미 식별자 값이 있는 상태로 save() 를 호출한다. 따라서 이 경우 merge() 가 호출된다. merge() 는 우선 DB..
스프링 데이터 JPA 구현체 분석
2022. 7. 22. 15:12
JPA/JPA-Spring Data
스프링 데이터 JPA가 제공하는 공통 인터페이스의 구현체 org.springframework.data.jpa.repository.support.SimpleJpaRepository 리스트 12.31 SimpleJpaRepository @Repository @Transactional(readOnly = true) public class SimpleJpaRepository ...{ @Transactional public S save(S entity) { if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } ... } @Repository 적용: JPA 예외를 스프링..
Web 확장 - 페이징과 정렬
2022. 7. 22. 13:51
JPA/JPA-Spring Data
스프링 데이터가 제공하는 페이징과 정렬 기능을 스프링 MVC에서 편리하게 사용할 수 있다. 페이징과 정렬 예제 @GetMapping("/members") public Page list(Pageable pageable) { Page page = memberRepository.findAll(pageable); return page; } 파라미터로 Pageable 을 받을 수 있다. Pageable 은 인터페이스, 실제는 org.springframework.data.domain.PageRequest 객체 생성 요청 파라미터 예) /members?page=0&size=3&sort=id,desc&sort=username,desc page: 현재 페이지, 0부터 시작한다. size: 한 페이지에 노출할 데이터 건수..
Web 확장 - 도메인 클래스 컨버터
2022. 7. 22. 02:11
JPA/JPA-Spring Data
HTTP 파라미터로 넘어온 엔티티의 아이디로 엔티티 객체를 찾아서 바인딩 도메인 클래스 컨버터 사용 전 @RestController @RequiredArgsConstructor public class MemberController { private final MemberRepository memberRepository; @GetMapping("/members/{id}") public String findMember(@PathVariable("id") Long id) { Member member = memberRepository.findById(id).get(); return member.getUsername(); } } 도메인 클래스 컨버터 사용 후 @RestController @RequiredArgsC..
Auditing
2022. 7. 21. 22:12
JPA/JPA-Spring Data
엔티티를 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶으면? 등록일 수정일 등록자 수정자 순수 JPA 사용 우선 등록일, 수정일 적용 package study.datajpa.entity; @MappedSuperclass @Getter public class JpaBaseEntity { @Column(updatable = false) private LocalDateTime createdDate; private LocalDateTime updatedDate; @PrePersist public void prePersist() { LocalDateTime now = LocalDateTime.now(); createdDate = now; updatedDate = now; } @PreUpdate public ..
사용자 정의 리포지토리 구현
2022. 7. 21. 20:33
JPA/JPA-Spring Data
스프링 데이터 JPA 리포지토리는 인터페이스만 정의하고 구현체는 스프링이 자동 생성 스프링 데이터 JPA가 제공하는 인터페이스를 직접 구현하면 구현해야 하는 기능이 너무 많음 다양한 이유로 인터페이스의 메서드를 직접 구현하고 싶다면? JPA 직접 사용( EntityManager ) 스프링 JDBC Template 사용 MyBatis 사용 데이터베이스 커넥션 직접 사용 등등... Querydsl 사용 사용자 정의 인터페이스 public interface MemberRepositoryCustom { List findMemberCustom(); } 사용자 정의 인터페이스 구현 클래스 @RequiredArgsConstructor public class MemberRepositoryImpl implements M..
JPA Hint & Lock
2022. 7. 21. 20:08
JPA/JPA-Spring Data
JPA Hint JPA 쿼리 힌트(SQL 힌트가 아니라 JPA 구현체에게 제공하는 힌트) @QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true")) Member findReadOnlyByUsername(String username); Lock @Lock(LockModeType.PESSIMISTIC_WRITE) List findByUsername(String name); org.springframework.data.jpa.repository.Lock 어노테이션을 사용 JPA가 제공하는 락은 JPA 책 16.1 트랜잭션과 락 절을 참고 출처 : 김영한 JPA 스프링 데이터 강의
@EntityGraph
2022. 7. 21. 15:07
JPA/JPA-Spring Data
//공통 메서드 오버라이드 @Override @EntityGraph(attributePaths = {"team"}) List findAll(); //JPQL + 엔티티 그래프 @EntityGraph(attributePaths = {"team"}) @Query("select m from Member m") List findMemberEntityGraph(); //메서드 이름으로 쿼리에서 특히 편리하다. @EntityGraph(attributePaths = {"team"}) List findByUsername(String username) EntityGraph 정리 사실상 페치 조인(FETCH JOIN)의 간편 버전 LEFT OUTER JOIN 사용 NamedEntityGraph 사용 방법 @NamedEnt..
벌크성 수정 쿼리
2022. 7. 21. 03:02
JPA/JPA-Spring Data
JPA를 사용한 벌크성 수정 쿼리 public int bulkAgePlus(int age) { int resultCount = em.createQuery( "update Member m set m.age = m.age + 1" + "where m.age >= :age") .setParameter("age", age) .executeUpdate(); return resultCount; } JPA를 사용한 벌크성 수정 쿼리 테스트 @Test public void bulkUpdate() throws Exception { //given memberJpaRepository.save(new Member("member1", 10)); memberJpaRepository.save(new Member("member2",..
스프링 데이터 JPA 페이징과 정렬
2022. 7. 20. 20:45
JPA/JPA-Spring Data
페이징과 정렬 파라미터 org.springframework.data.domain.Sort : 정렬 기능 org.springframework.data.domain.Pageable : 페이징 기능 (내부에 Sort 포함) 특별한 반환 타입 org.springframework.data.domain.Page : 추가 count 쿼리 결과를 포함하는 페이징 org.springframework.data.domain.Slice : 추가 count 쿼리 없이 다음 페이지만 확인 가능(내부적으로 limit + 1조회) List (자바 컬렉션): 추가 count 쿼리 없이 결과만 반 Page 인터페이스 public interface Page extends Slice { int getTotalPages(); //전체 페이지..
순수 JPA 페이징과 정렬
2022. 7. 20. 18:15
JPA/JPA-Spring Data
public List findByPage(int age, int offset, int limit) { return em.createQuery("select m from Member m where m.age = :age order by m.username desc") .setParameter("age", age) .setFirstResult(offset) .setMaxResults(limit) .getResultList(); } public long totalCount(int age) { return em.createQuery("select count(m) from Member m where m.age = :age", Long.class) .setParameter("age", age) .getSingleR..
파라미터 바인딩
2022. 7. 20. 13:15
JPA/JPA-Spring Data
select m from Member m where m.username = ?0 //위치 기반 select m from Member m where m.username = :name //이름 기반 import org.springframework.data.repository.query.Param public interface MemberRepository extends JpaRepository { @Query("select m from Member m where m.username = :name") Member findMembers(@Param("name") String username); } 컬렉션 파라미터 바인딩 Collection 타입으로 in절 지원 @Query("select m from Member..
@Query, 값, DTO 조회하기
2022. 7. 20. 12:46
JPA/JPA-Spring Data
@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) " + "from Member m join m.team t") List findMemberDto(); package study.datajpa.repository; import lombok.Data; @Data public class MemberDto { private Long id; private String username; private String teamName; public MemberDto(Long id, String username, String teamName) { this.id = id; this.username = username; this.teamName ..
@Query, 리포지토리 메소드에 쿼리 정의하기
2022. 7. 20. 12:31
JPA/JPA-Spring Data
public interface MemberRepository extends JpaRepository { @Query("select m from Member m where m.username= :username and m.age = :age") List findUser(@Param("username") String username, @Param("age") int age); } 출처 : 김영한 JPA 스프링 데이터 강의
JPA NamedQuery
2022. 7. 19. 21:02
JPA/JPA-Spring Data
* @NamedQuery 어노테이션으로 Named 쿼리 정의* @Entity @NamedQuery( name="Member.findByUsername", query="select m from Member m where m.username = :username") public class Member { ... } JPA를 직접 사용해서 Named 쿼리 호출 public class MemberRepository { public List findByUsername(String username) { ... List resultList = em.createNamedQuery("Member.findByUsername", Member.class) .setParameter("username", username) .ge..
메소드 이름으로 쿼리 생성
2022. 7. 19. 18:17
JPA/JPA-Spring Data
public interface MemberRepository extends JpaRepository { List findByUsernameAndAge(String username, int age); } 순수 JPA 리포지토리 public List findByUsernameAndAge(String username, int age) { return em.createQuery("select m from Member m where m.username = :username and m.age > :age") .setParameter("username", username) .setParameter("age", age) .getResultList(); } 순수 JPA 테스트 코드 @Test public void fin..
공통 인터페이스 설정
2022. 7. 19. 17:38
JPA/JPA-Spring Data
1. 공통 인터페이스 설정 JavaConfig 설정- 스프링 부트 사용시 생략 가능 @Configuration @EnableJpaRepositories(basePackages = "jpabook.jpashop.repository") public class AppConfig {} 스프링 데이터 JPA가 구현 클래스 대신 생성 public interface MemberRepository extends JpaRepository { } JpaRepository 인터페이스: 공통 CRUD 제공 제네릭은 설정 주의 T findOne(ID) Optional findById(ID) 변경 제네릭 타입 T : 엔티티ID : 엔티티의 식별자 타입 S : 엔티티와 그 자식 타입 주요 메서드 save(S) : 새로운 엔티티는 ..
순수 JPA 기반 리포지토리 만들기
2022. 7. 19. 02:41
JPA/JPA-Spring Data
package study.datajpa.repository; import org.springframework.stereotype.Repository; import study.datajpa.entity.Member; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.util.List; import java.util.Optional; @Repository public class MemberJpaRepository { @PersistenceContext private EntityManager em; public Member save(Member member) { em.persist(mem..