Notice
Recent Posts
Recent Comments
Link
아님말고
[JPA] Projection 의 다양한 방법들 본문
Projection는 JPA로 조회시 원하는 컬럼을 가져오는 방식으로
Spring Data JPA 에서 사용하는 방식과 QueryDSL 에서 사용하는 방식으로 나눠서 볼 수 있습니다.
Member.java
@Data
@Entity
@Table(name = "member")
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String email;
}
Spring Data JPA 에서 사용하는 방식
크게 Interface 방식과 Class 방식이 있다.
Interface 기반 Projections
Closed Projections
Member 에서 id, name 만 가져와보자. Interface 를 만들고 repository 에서 해당 interface 로 담는 메소드만 만들어주면 된다.
public interface MemberSummary {
int getId();
String getName();
}
public interface MemberRepository extends JpaRepository<Member, Integer>, MemberRepositoryCustom {
List<MemberSummary> findByNameContains(String name);
}
Open Projections
모든 컬럼을 가져와 interface 메소드에 맞게 혼합한다. 모든 컬럼을 가져오기에 비추.
public interface MemberSummary {
int getId();
String getName();
@Value("#{target.id + ' ' + target.name}")
String getIdAndName();
}
아래와 같은 방법을 사용하자.
public interface MemberSummary {
int getId();
String getName();
default String getIdAndName() {
return getId() + " " + getName();
}
}
class 기반 Projections
DTO 파일을 하나 만들어서 사용하면 된다.
public class MemberSummary {
private int id;
private String name;
public MemberSummary(int id, String name){
this.id = id;
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
}
Dynamic Projections
Member 에서 name 으로 조회하는데 service 1에서는 id, name 만 가져오고, service 2에서는 id, email 만 가져오고 싶을때
repository 의 메소드는 동일하고 담는 객체만 다른 경우 아래와 같이 한다.
public interface MemberRepository extends JpaRepository<Member, Integer>, MemberRepositoryCustom {
<T> T findByNameContains(String Name, Class<T> type);
}
QueryDSL 에서 사용하는 방식
DTO를 만들고 해당 DTO의 setter를 이용하거나, field에 직접 주입하거나, 생성자를 이용한다.
@Data
@AllArgsConstructor
public class MemberDTO {
private int id;
private String name;
}
Projections.bean()
List<MemberDTO> content = jpaQueryFactory
.select(Projections.bean(MemberDTO.class,
qMember.id,
qMember.name))
.from(qMember)
.where(qMember.name.contains(name))
.fetch();
Projections.fields()
List<MemberDTO> content = jpaQueryFactory
.select(Projections.fields(MemberDTO.class,
qMember.id,
qMember.name))
.from(qMember)
.where(qMember.name.contains(name))
.fetch();
Projections.constructor()
List<MemberDTO> content = jpaQueryFactory
.select(Projections.constructor(MemberDTO.class,
qMember.id,
qMember.name))
.from(qMember)
.where(qMember.name.contains(name))
.fetch();
@QueryProjection
DTO 의 Q파일을 이용하는데 컴파일 시점에 오류를 확인 가능하여 좀 더 안전한 소스를 만들 수 있다.
자세한 소스는 아래 URL에서 확인.
'JPA' 카테고리의 다른 글
[JPA] QueryDSL 조회시 원하는 컬럼만 가져오기 (0) | 2022.09.14 |
---|---|
[JPA] QueryDSL 초기 세팅 및 예제 (0) | 2022.09.09 |
[JPA] org.hibernate.hql.internal.ast.QuerySyntaxException: 엔티티명 is not mapped (0) | 2022.08.29 |
[JPA] QueryDSL + multi datasource 설정 (0) | 2022.08.17 |
[JPA] query를 작성하는 방법들 (0) | 2022.08.10 |
Comments