Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Application Runner
- 정적 리소스
- JPA
- EnableAutoConfiguration
- HttpMessageConverters
- 리소스핸들러
- 알고리즘
- WebApplication Type
- cors
- JsonSerializer
- 다익스트라
- @ConfigurationProperties
- Spring Security
- 브루트포스
- OAuth2
- 백준
- HATEOAS
- @Profile
- 외부설정
- 백기선
- rest api
- webjar
- Application Argument
- Application Event
- 스프링부트
- 스프링 부트
- AuthenticationPrincipal
- 백트래킹
- 리소스 서버
- application.properties
Archives
- Today
- Total
아카이브
[스프링 데이터 JPA] 스프링 데이터 JPA 8. Projection 본문
엔티티의 일부 데이터만 가져오기
인터페이스 기반 Projection
- Nested 프로젝션 가능
- Closed 프로젝션
- 일부만 가져오기
- 쿼리를 최적화할 수 있다. 가져오려는 애트리뷰트가 뭔지 알고 있으니까
- Java 8의 디폴트 메서드를 사용해서 연산을 할 수 있다
- Open 프로젝션
- 전부 다 가져와서 가공하기
- @Value(SpEL)을 사용해서 연산할 수 있다. 스프링 빈의 메서드 호출도 가능
- 쿼리 최적화를 할 수 없다. SpEL을 엔티티 대상으로 사용하기 때문에
클래스 기반 Projection
- DTO
- Lombok @Value로 코드 줄일 수 있음
다이내믹 Projection
- 프로젝션용 메서드 하나만 정의하고, 실제 프로젝션 타입은 파라미터로 전달하기
<T> List<T> findByPost_Id(Long id, Class<T> type);
1. Closed Projection 실습
Comment 엔티티에 필드 추가
@NamedEntityGraph(name = "Comment.post", attributeNodes = @NamedAttributeNode("post"))
@Entity
@Getter
@Setter
public class Comment {
@Id
@GeneratedValue
private Long id;
private String comment;
/*
* ManyToOne에서 fetch default = EAGER
* */
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
private Date created;
private Integer likeCount = 0;
/* 필드 추가 */
private int up;
private int down;
private boolean best;
}
CommentSummary 인터페이스 추가
public interface CommentSummary {
String getComment();
int getUp();
int getDown();
}
CommentRepository에 Closed Projection 방식의 메서드 추가하기
public interface CommentRepository extends MyRepository<Comment, Long> {
/* CommentSummary로 한정적인 필드들만 받아온다 */
List<CommentSummary> findByPost_id(Long id);
}
2. Open Projection 실습
CommentSummary에 Open Projection 필드 추가하기
@Value("#{target.up + ' ' + target.down}")
String getVotes();
- target==comment. 모든 필드를 가져와서 조합하기 때문에 Open Projection이라 칭한다.
3. Open Projection의 장점 + Closed Projection 사용하기
CommentSummary에 default method 추가
- Java8부터 인터페이스에 default 메서드를 추가할 수 있다.
- 이에 따라 Closed Projection 인터페이스에 default 메서드를 추가하여
- 필드를 한정지어 가져오고(쿼리 최적화)
- 조합이나 연산이 가능하게 할 수 있다(Open Projection의 장점)
- 가장 좋은 방법으로 권장.
package me.jumen.springdatajpa;
public interface CommentSummary {
String getComment();
int getUp();
int getDown();
/**
* Open Projection의 장점을 살리면서 Closed 로 동작하게 하는 방법
* 쿼리 최적화 + custom 구현체
* 가장 좋은 방법이다.
* */
default String getVotes() {
return getUp() + " " + getDown();
}
}
4. 다이나믹 Projection
- 프로젝션용 메서드 하나만 정의하고, 실제 프로젝션 타입은 파라미터로 전달한다.
- Repository에 쿼리 메서드를 더 추가하지 않고, 간결하게 다양화할 수 있다.
CommentOnly 인터페이스 추가
public interface CommentOnly {
String getComment();
}
CommentRepository에 프로젝션 타입 메서드 추가하기
/* Dynamic Projection */
<T> List<T> findByPost_id(Long id, Class<T> type);
테스트 코드
@Test
public void getCommentSummaryByPostId() {
Post post = new Post();
post.setTitle("jpa");
Post savedPost = postRepository.save(post);
Comment comment = new Comment();
comment.setComment("spring data jpa projection");
comment.setPost(savedPost);
comment.setUp(10);
comment.setDown(1);
commentRepository.save(comment);
/**
* Dynamic Projection
* Projection 메서드 하나만 정의하고, 실제 Projection type은 parameter로 전달하여
* 별도의 쿼리 메서드를 추가하지 않고 다양하게 만들 수 있다.
* */
/* CommentSummary */
commentRepository.findByPost_id(1l, CommentSummary.class).forEach(c -> {
System.out.println("=====================");
System.out.println(c.getVotes());
});
/* CommentOnly */
commentRepository.findByPost_id(1l, CommentOnly.class).forEach(c -> {
System.out.println("=====================");
System.out.println(c.getComment());
});
}
'Spring > 스프링 데이터 JPA' 카테고리의 다른 글
[스프링 데이터 JPA] 스프링 데이터 JPA 10. 트랜잭션 (0) | 2021.01.17 |
---|---|
[스프링 데이터 JPA] 스프링 데이터 JPA 9. Specifications (0) | 2021.01.17 |
[스프링 데이터 JPA] 스프링 데이터 JPA 7. EntityGraph (0) | 2021.01.16 |
[스프링 데이터 JPA] 스프링 데이터 JPA 6. Update 쿼리 (0) | 2021.01.16 |
[스프링 데이터 JPA] 스프링 데이터 JPA 5. 쿼리 메서드 Named Parameter과 SpEL (0) | 2021.01.16 |