항해99/TIL

54일차-7/30 금 -항해99 TIL

고로케 2021. 7. 31.
반응형

하루 회고

  • JPA 로 머리가 아프다. 내가 원하는 값만 가져오고 싶어 제발

post 에 user를 연결했더니, 게시글 내려갈때 user비밀번호 내려감 하하하ㅏㅎㅎ히힣히힣히

JPQL 로 해결할 수 있을 것 같은데 좀 더 찾아봐야겠다.
아직도 쿼리의 늪에서 너무 집중 못하고 이것저것 찾아보니까 방황만 하는 느낌ㅠㅠ

이것만 되면 진짜 다 조조관우장비해버릴 것 같아

주저리 주저리

바다가고싶어요! 강화도에서 부시리먹자!! 헤르미온느 부시리!

오늘 배운 것

나는 사랑둥이 참돔이다..?

Projection

엔티티의 일부 데이터만 가져오기.

  • 인터페이스 기반 프로젝션
    • Nested 프로젝션 가능.
    • Closed 프로젝션
      • 쿼리를 최적화 할 수 있다. 가져오려는 애트리뷰트가 뭔지 알고 있으니까.
      • Java 8의 디폴트 메소드를 사용해서 연산을 할 수 있다.
  • Open 프로젝션
    • @Value(SpEL)을 사용해서 연산을 할 수 있다. 스프링 빈의 메소드도 호출 가능.
    • 쿼리 최적화를 할 수 없다. SpEL을 엔티티 대상으로 사용하기 때문에.
  • 클래스 기반 프로젝션
    • DTO
    • 롬복 @Value로 코드 줄일 수 있음
  • 다이나믹 프로젝션
    • 프로젝션 용 메소드 하나만 정의하고 실제 프로젝션 타입은 타입 인자로 전달하기.

<T> List<T> findByPost_Id(Long id, Class<T> type);

Close 프로젝션

간단한 예제실습

Comment.java

@Entity
public class Comment {

    @Id
    @GeneratedValue
    private Long id;

    private String comment;

    @ManyToOne(fetch = FetchType.EAGER)
    private Post post;

    private int up;

    private int down;

    private boolean best;
}

Comment 엔티티에서 가져와야할 정보는 comment, up, down 세가지 입니다. 인터페이스 기반 프로젝션으로 가져오기

CommentSummary.java

public interface CommentSummary {

    String getComment();
    int getUp();
    int getDown();
}

CommentRepository.java

public interface CommentRepository extends JpaRepository<Comment, Long> {

    List<CommentSummary> findByPost_Id(Long id);
}

CommentSummary 타입으로 바꾸면 원하는 값만 출력됩니다.

Hibernate: 
    select
        comment0_.comment as col_0_0_,
        comment0_.up as col_1_0_,
        comment0_.down as col_2_0_ 
    from
        comment comment0_ 
    left outer join
        post post1_ 
            on comment0_.post_id=post1_.id 
    where
        post1_.id=?

Open 프로젝션

CommentSummary.java

public interface CommentSummary {

    String getComment();
    int getUp();
    int getDown();

    @Value("#{target.up + ' ' + target.down}")
    String getVotes();
}

target 은 comment 입니다. comment를 전부 가져와서 한정이 없어서 오픈 프로젝션입니다. 성능 최적화는 없습니다. 다만 문자열을 만들어서 가져올 수 있다는 특징이 있습니다.

CommentRepositoryTest.java

@DataJpaTest
class CommentRepositoryTest {

    @Autowired
    CommentRepository commentRepository;

    @Autowired
    PostRepository postRepository;
sequence

    @Test
    public void getComment() {
        Post post = new Post();
        post.setTitle("Spring");
        Post savePost = postRepository.save(post);

        Comment comment = new Comment();
        comment.setPost(savePost);
        comment.setUp(10);
        comment.setDown(1);
        commentRepository.save(comment);

        commentRepository.findByPost_Id(savePost.getId()).forEach(c -> {
           System.out.println("=======");
           System.out.println(c.getVotes());
           System.out.println("=======");
        });
    }
}
=======
10 1
=======

Open 프로젝션을 Close으로

이러한 장점을 살리면서 한정적으로 쿼리를 만드는 방법

public interface CommentSummary {

    String getComment();

    int getUp();

    int getDown();

    default String getVotes() {
        return getUp() + "show!!" + getDown();
    }
}
=======
10show!!1
=======

여러가지 조건을 넣어 사용하기 위해서 제네릭을 사용합니다.

public interface CommentRepository extends JpaRepository<Comment, Long> {

    <T> List<T> findByPost_Id(Long id, Class<T> type);
}

어떠한 타입의 프로젝션 클래스 타입을 줘야합니다.

commentRepository.findByPost_Id(savePost.getId(), CommentSummary.class).forEach(c -> {
    System.out.println("=======");
    System.out.println(c.getVotes());
});
반응형

'항해99 > TIL' 카테고리의 다른 글

56일차_8/01_항해99 -8주차 WIL(회고록)  (3) 2021.08.08
55일차-7/31 토 TIL -항해99 일지  (0) 2021.08.08
53일차-7/29 목 -항해99 TIL  (1) 2021.07.30
52일차-7/28 수 -항해99 TIL  (1) 2021.07.29
51일차-7/27 화 -항해99 TIL  (0) 2021.07.28

댓글