페이징
2022. 7. 24. 20:28
Querydsl
조회 건수 제한 @Test public void paging1() { List result = queryFactory .selectFrom(member) .orderBy(member.username.desc()) .offset(1) //0부터 시작(zero index) .limit(2) //최대 2건 조회 .fetch(); assertThat(result.size()).isEqualTo(2); } 전체 조회 수가 필요하면? @Test public void paging2() { QueryResults queryResults = queryFactory .selectFrom(member) .orderBy(member.username.desc()) .offset(1) .limit(2) .fetchResults(..
정렬
2022. 7. 24. 19:42
Querydsl
/** * 회원 정렬 순서 * 1. 회원 나이 내림차순(desc) * 2. 회원 이름 올림차순(asc) * 단 2에서 회원 이름이 없으면 마지막에 출력(nulls last) */ @Test public void sort() { em.persist(new Member(null, 100)); em.persist(new Member("member5", 100)); em.persist(new Member("member6", 100)); List result = queryFactory .selectFrom(member) .where(member.age.eq(100)) .orderBy(member.age.desc(), member.username.asc().nullsLast()) .fetch(); Member me..
결과 조회
2022. 7. 24. 17:06
Querydsl
fetch() : 리스트 조회, 데이터 없으면 빈 리스트 반환 fetchOne() : 단 건 조회 결과가 없으면 : null 결과가 둘 이상이면 : com.querydsl.core.NonUniqueResultException fetchFirst() : limit(1).fetchOne() fetchResults() : 페이징 정보 포함, total count 쿼리 추가 실행 fetchCount() : count 쿼리로 변경해서 count 수 조회 //List List fetch = queryFactory .selectFrom(member) .fetch(); //단 건 Member findMember1 = queryFactory .selectFrom(member) .fetchOne(); //처음 한 건 조회..
검색 조건 쿼리
2022. 7. 24. 15:46
Querydsl
기본 검색 쿼리 @Test public void search() { Member findMember = queryFactory .selectFrom(member) .where(member.username.eq("member1").and(member.age.eq(10))) .fetchOne(); assertThat(findMember.getUsername()).isEqualTo("member1"); } 검색 조건은 .and() , . or() 를 메서드 체인으로 연결할 수 있다. 참고: select , from 을 selectFrom 으로 합칠 수 있음 JPQL이 제공하는 모든 검색 조건 제공 member.username.eq("member1") // username = 'member1' member.us..
기본 Q-Type 활용
2022. 7. 24. 15:33
Querydsl
Q클래스 인스턴스를 사용하는 2가지 방법 QMember qMember = new QMember("m"); //별칭 직접 지정 QMember qMember = QMember.member; //기본 인스턴스 사용 기본 인스턴스를 static import와 함께 사용 import static study.querydsl.entity.QMember.*; @Testpublic void startQuerydsl3() { //member1을 찾아라. Member findMember = queryFactory .select(member) .from(member) .where(member.username.eq("member1")) .fetchOne(); assertThat(findMember.getUsername()).i..
JPQL vs Querydsl
2022. 7. 24. 15:02
Querydsl
@Test public void startJPQL() { //member1을 찾아라. String qlString = "select m from Member m " + "where m.username = :username"; Member findMember = em.createQuery(qlString, Member.class) .setParameter("username", "member1") .getSingleResult(); assertThat(findMember.getUsername()).isEqualTo("member1"); } @Test public void startQuerydsl() { //member1을 찾아라. JPAQueryFactory queryFactory = new JPAQuery..
Querydsl 설정과 검증
2022. 7. 23. 23:14
Querydsl
build.gradle 에 주석을 참고해서 querydsl 설정 추가 plugins { id 'org.springframework.boot' version ‘2.2.2.RELEASE' id 'io.spring.dependency-management' version '1.0.8.RELEASE' //querydsl 추가 id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" id 'java' }group = 'study' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { ..
네이티브 쿼리
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..