Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

아님말고

[JPA] Projection 의 다양한 방법들 본문

JPA

[JPA] Projection 의 다양한 방법들

스타박씨 2022. 9. 15. 13:42

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] QueryDSL 조회시 원하는 컬럼만 가져오기 (tistory.com)

Comments