728x90
반응형
Projection은 Entity의 속성이 많을 때 일부 데이터만 조회하는 방법입니다.
아래 UserEntity를 참고하여 설명하겠습니다.
@Entity
@Table(name = "user")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserEntity {
@Id
@Column(name = "user_id", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
@Column(length = 50, nullable = false)
private String name;
@Column(length = 50, nullable = false)
private String lastname;
private int age;
@Column(name = "email_address", length = 200)
private String emailAddress;
}
1. Closed Projections
name과 lastname만 조회하고 싶다고 가정하여 인터페이스를 생성합니다.
public class UserDTO {
public interface UserSummary {
String getName();
String getLastname();
}
}
만든 인터페이스 타입으로 쿼리를 만들고 실행시켜주면
public interface UserRepository extends JpaRepository<UserEntity, Long> {
UserDTO.UserSummary findByLastname(String lastname);
List<UserDTO.UserSummary> findAllByAge(int age);
}
name과 lastname만 조회해오는 것을 확인할 수 있습니다.
2. Open Projections
open projections는 모든 요소를 조회해와서 두 개의 요소를 합쳐서 보여줄 수 있습니다. 따라서 성능 최적화는 불가능합니다.
public class UserDTO {
public interface UserSummary {
String getName();
String getLastname();
@Value("#{target.name + ' ' + target.lastname}")
String getFullName();
}
}
그래서 아래와 같이 필요한 요소만 가져와 커스텀할 수 있습니다.
public class UserDTO {
public interface UserSummary {
String getName();
String getLastname();
default String getFullName() {
return getName().concat(" ").concat(getLastname());
}
}
}
3. Dynamic Projections
아래와 같이 두 가지 타입의 Projection으로 값을 받고 싶을 때
public class UserDTO {
public interface UserSummary {
String getName();
String getLastname();
}
public interface AgeOnly {
int getAge();
}
}
메서드 명이 같으면 오류가 발생합니다. 이런 경우 Generic 타입을 사용하면 됩니다.
UserDTO.UserSummary result1 = userRepository.findByLastnameEquals(lastname, UserDTO.UserSummary.class);
UserDTO.AgeOnly result2 = userRepository.findByLastnameEquals(lastname, UserDTO.AgeOnly.class);
4. QueryDsl에서 Projection 사용
public class UserDTO {
@Getter @Setter
@NoArgsConstructor
public static class GetRes {
private String name;
private String lastname;
private int age;
public GetRes(String name, String lastname, int age) {
this.name = name;
this.lastname = lastname;
this.age = age;
}
}
}
@RequiredArgsConstructor
public class UserRepositoryCustomImpl implements UserRepositoryCustom {
private final JPAQueryFactory queryFactory;
private static final QUserEntity userEntity = QUserEntity.userEntity;
@Override
public List<UserDTO.GetRes> findAllOrderByIdDesc(UserDTO.GetListReq param) {
return queryFactory.select(Projections.constructor(UserDTO.GetRes.class,
userEntity.userId, userEntity.userName, userEntity.age))
.from(userEntity)
.where(userEntity.age.eq(param.getAge()))
.orderBy(userEntity.id.desc())
.fetch();
}
}
[Reference]
https://docs.spring.io/spring-data/commons/docs/2.5.2/reference/html/#projections
728x90
반응형
'spring > spring jpa' 카테고리의 다른 글
[QueryDSL] FullText 검색을 위한 Match ... against 절 사용법 (0) | 2023.08.24 |
---|---|
[SpringBoot] QueryDSL org.apache.jasper.JasperException: Unable to compile class for JSP: (0) | 2023.08.24 |
[SpringBoot2] JPA Master/Slave 구조 분기 처리 (2) | 2023.08.23 |
[Spring] JPA 연관 관계 매핑 및 제거 (0) | 2021.06.18 |
[SpringBoot] Mybatis + JPA + QueryDsl 설정 (0) | 2021.06.10 |
댓글