Language`/JPA(32)
-
[QueryDSL] 동적 쿼리 (BooleanExpression)
QueryDSL은 SQL자체를 자바 코드로 작성하기 때문에 TypeSafe하고 컴파일 시점에 오류를 발견할 수 있다는 장점이 존재한다. 더불어서 QueryDSL의 가장 큰 장점 중 하나는 "동적 쿼리 생성의 편리함"이다 QueryDSL에서 where절에 동적 쿼리를 생성하기 위해서는 "BooleanExpression"을 활용하면 된다 BooleanExpression BooleanExpression을 return하는 "동적 쿼리 전용 메소드"를 만들면 굉장히 편리하게 특정 조건에 따른 동적 쿼리를 작성할 수 있다 Integer ageUpper = 25; String userNameContains = "nus1"; List fetch = query.selectFrom(member) .where(member...
2022.08.28 -
[QueryDSL] 프로젝션, DTO 조회
프로젝션 프로젝션이란 "Select절에 조회 대상을 지정"하는 것이다 대상 하나 조회대상이 하나라면 Return Type은 해당 조회 대상의 Type으로 정해진다 // Projection [Member] List fetch1 = query.select(member) .from(member) .where(member.age.goe(25)) .fetch(); // Projection [String] List fetch2 = query.select(member.username) .from(member) .where(member.age.goe(25)) .fetch(); // Projection [Integer] List fetch3 = query.select(member.age) .from(member) .wh..
2022.08.28 -
[QueryDSL] Join & SubQuery
QueryDSL Join QueryDSL에서는 JPQL에서 지원하는 [InnerJoin, LeftOuterJoin]은 당연하게 사용할 수 있고 더해서 [RightOuterJoin]도 사용할 수 있다 추가적으로 on절과 더불어서 성능 최적화를 위한 FetchJoin도 활용할 수 있다 InnerJoin 첫번째 파라미터(Root Entity에 대한 조인 대상) 두번째 파라미터(조인 대상의 Alias) List fetch = query.selectFrom(member) .innerJoin(member.team, team) .where(member.age.goe(25).and(team.name.eq("Team-A"))) .fetch(); for (Member member : fetch) { System.out.p..
2022.08.28 -
[QueryDSL] 정렬 & 페이징
정렬 QueryDSL에서의 정렬은 "orderBy()"메소드를 통해서 내부적으로 정렬 기준의 필드에 대해서 [asc(), desc()]를 통해서 정렬하면 된다 // 25살 이상 Member들에 대한 "나이 오름차순/이름 내림차순 정렬" List fetch = query.selectFrom(member) .where(member.age.goe(25)) .orderBy(member.age.asc(), member.username.desc()) .fetch(); 페이징 페이징은 "offset() & limit()"를 통해서 시작 지점/페이징 개수를 적절하게 조합해서 활용하면 된다 offset번째부터 limit개수의 페이징 처리를 한다는 의미이다 QueryDSL에서 offset의 가장 처음 기준은 "0"이다 P..
2022.08.27 -
[QueryDSL] 기본적인 조회
JPAQueryFactory 기본적으로 QueryDSL을 통해서 query를 생성하기 위해서는 "JPAQueryFactory"로부터 쿼리를 생성해야 한다. 하지만 JPAQueryFactory가 필요한 모든 곳에서 JPAQueryFactory를 가져오는 것은 큰 낭비이고 JPAQueryFactory를 사용하기 위해서는 "EntityManager"도 필요하기 때문에 불편하다 >> JPAQueryFactory를 @Bean을 통해서 빈으로 등록해버리면 프로젝트 전역에서 편리하게 JPAQueryFactory를 사용할 수 있게 된다 @Configuration public class QueryDSLConfig { @PersistenceContext private EntityManager em; @Bean JPAQue..
2022.08.26 -
[QueryDSL] QueryDSL 기본 설정
1) build.gradle 의존성 추가 dependencies { ... ... //Querydsl 추가 implementation 'com.querydsl:querydsl-jpa' annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jpa" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" } querydsl-jpa = QueryDSL의 JPA 라이브러리 querydsl-apt = QueryDSL에서 사용할 "쿼리 타입(Q)"를 생성할 때 필요한 라이브러리 jakarta.anno..
2022.08.26 -
[Spring Data JPA] Web Binding
Parameter로 Member의 id(PK)가 넘어오고 이를 통해서 멤버를 조회하는 일반적인 로직을 작성해보자 // Controller @RestController @RequiredArgsConstructor public class TestController { private final MemberService memberService; @GetMapping("/member") public Member getMember(@RequestParam Long id) { return memberService.findMember(id); } } // Service @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class Memb..
2022.08.23 -
[Spring Data JPA] 사용자 정의 Repository
일반적으로 Spring Data JPA를 활용하면 인터페이스만 정의하고 그에 대한 구현체는 정의하지 않는다 왜냐하면 Spring의 ProxyFactory에 의해서 정의한 인터페이스에 대한 "프록시"를 생성하고 이 프록시 내부적으로 실제 JpaRepository의 구현체인 "SimpleJpaRepository"를 호출하도록 설계되었기 때문이다 private final MemberRepository memberRepository; @Test @DisplayName("Spring Data JPA 인터페이스 프록시 확인") void proxyTest() { System.out.println(memberRepository.getClass()); assertThat(AopUtils.isAopProxy(memberR..
2022.08.23 -
[Spring Data JPA] 페이징 & 정렬
JPQL을 통해서 페이징을 하기 위해서는 [setFirstResult(), setMaxResults()]를 통해서 페이징 처리를 하였다. 그리고 정렬을 하기 위해서는 직접 SQL Query에 정렬 기준을 명시해주었다 하지만 Spring Data JPA에서는 다음 2가지 특별한 파라미터를 제공해주고, 이 파라미터들을 통해서 페이징/정렬을 굉장히 편리하게 구현할 수 있다 org.springframework.data.domain.Sort = 정렬 org.springframework.data.domain.Pageable = 페이징 기능 (내부에 Sort 포함) 페이징에 대한 return type으로는 List/Page를 사용할 수 있다. Page는 기본적으로 Slice를 확장한 인터페이스이고, 반환타입으로 Pa..
2022.08.19 -
[Spring Data JPA] 쿼리 메소드 기능
더보기 ## 쿼리 메소드 기능을 테스트할 기본적인 엔티티 구성 @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @Table(name = "member") public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "member_id") private Long id; @Column(name = "user_name", length = 50) private String username; private Integer age; @Enumerated(EnumType.STRING) private MemberType type; @Column(..
2022.08.18 -
[JPA] 벌크 연산
벌크 연산 Entity를 수정하기 위해서는 [Dirty Checking, Merge]를 사용하고, 삭제하기 위해서는 [remove()]를 사용한다 1-1. 수정 (벌크 연산 X) List memberList = new ArrayList(); for (long i = 1L; i 이럴때는 여러 건을 한번에 수정/삭제해주는 "벌크 연산"을 사용하면 된다 벌크 연산을 활용하려면 em.createQuery에 벌크 연산을 수행할 쿼리를 넣어주고 "executeUpdate()"를 호출해주면 된다 executeUpdate()의 Return Value는 "DB상에서 변화된 Tuple의 개수"이다 2-1. 수정 (벌크 연산 O) String sql = "UPDATE Member m " + "SET m.age = 100";..
2022.08.11 -
[JPA] Named 쿼리
1. 동적 쿼리 (em.createQuery) 동적 쿼리는 말 그대로 createQuery 메소드를 활용해서 직접 JPQL을 만들어서 넘겨주는 쿼리이다 em.createQuery( "SELECT m" + " FROM Member m", Member.class ).getResultList(); em.createQuery( "SELECT m" + " FROM Member m" + " WHERE m.team.id = :teamId", Member.class ).setParameter("teamId", 1L) .getResultList(); em.createQuery( "SELECT t" + " FROM Team t" + " WHERE t.name LIKE '%A%'" + " ORDER BY t.name", T..
2022.08.11