스프링 데이터 JPA-04.Fetch, 쿼리


JPA 프로그래밍 6. Fetch

연관 관계의 엔티티를 어떻게 가져올 것인가? 지금(Eager)? 나중에(Lazy)?

  • @OneToMany의 기본값은 Lazy
  • @ManyToOne의 기본값은 Eager

포스트(@OneToMany)에 대한 정보를 가져올 때, 코멘트에 대한 정보는 가져오지 않는다. (필요하지도 않을 수도 있는데, 몇건이 될지도 모르는 코멘트들에 대한 정보 안가져옴, 정말 사용해야 한다면 그 시점에서 가져온다.)

근데 반대로 코멘트(@ManyToOne)에 대한 정보를 가져올때는, 포스트에 대한 정보는 가져온다. (1건 이기 때문에 어떻게 생각하면 합리적)

기본적으로 설정된 것을 설정을 통해서 변경이 가능하다.
ex.@OneToMany(mappedBy = “post”, cascade = CascadeType.ALL, fetch = FetchType.EAGER)

구현 및 설명

        Post post = session.get(Post.class, 1l); // 1l (1 Long type)
        System.out.println("======= Post ========");
        System.out.println(post.getTitle());

게시글 번호가 1인 것을 조회할때 코멘트는 가져오지 않는다.

하지만 게시글 번호가 2인 코멘트들도 사용해야 한다면 가져오는 것을 확인할 수 있다.

        Session session = entityManager.unwrap(Session.class);
        //session.save(post);

        Post post = session.get(Post.class, 2l);
        System.out.println("======= Post ========");
        System.out.println(post.getTitle());

        post.getComments().forEach(c-> {
            System.out.println("======== comment ========");
            System.out.println(c.getComment());
        });

        System.out.println("======== print =========");

실행결과

Hibernate: 
    select
        post0_.id as id1_2_0_,
        post0_.title as title2_2_0_ 
    from
        post post0_ 
    where
        post0_.id=?
======= Post ========
Jpa 공부중...
Hibernate: 
    select
        comments0_.post_id as post_id3_1_0_,
        comments0_.id as id1_1_0_,
        comments0_.id as id1_1_1_,
        comments0_.comment as comment2_1_1_,
        comments0_.post_id as post_id3_1_1_ 
    from
        comment comments0_ 
    where
        comments0_.post_id=?
======== comment ========
그러게 말이에요..
======== comment ========
언제 공부는 끝나시나요..
======== print =========

JPA 프로그래밍 7. 쿼리

JPQL (HQL)

  • Java Persistence Query Language / Hibernate Query Language
  • 데이터베이스 테이블이 아닌, 엔티티 객체 모델 기반으로 쿼리 작성.
  • JPA 또는 하이버네이트가 해당 쿼리를 SQL로 변환해서 실행함.
  • https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#hql
  • 단점 : 타입 세이프하지 않다. 문자열 쿼리기 때문에.
    @PersistenceContext // jpa 가장 핵심적인 빈
    EntityManager entityManager;

    @Override
    public void run(ApplicationArguments args) {
        TypedQuery<Post> query = entityManager.createQuery("SELECT p from Post As p", Post.class);
        List<Post> posts = query.getResultList();
        posts.forEach(System.out::print); 
        // toString() 구현 시 comment는 뺌. (comment 넣는다면 필요하니까 toString 사용시 comment도 같이 조회됨
    }
Hibernate: 
    select
        post0_.id as id1_2_,
        post0_.title as title2_2_ 
    from
        post post0_
Post{id=1, title='Jpa 공부중...}Post{id=2, title='Jpa 공부중...}

Criteria

  • 타입 세이프 쿼리
  • https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#criteria
    @Override
    public void run(ApplicationArguments args) {
        // 타입세이프 쿼리, 문자열이 하나도 들어가지 않는다.
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Post> criteria = builder.createQuery(Post.class);
        Root<Post> root = criteria.from(Post.class);
        criteria.select(root);
        List<Post> posts = entityManager.createQuery(criteria).getResultList();
        posts.forEach(System.out::print);
    }

실행결과 동일.

또한 마이바티스 처럼 한곳에다 쿼리를 선언해놓고 호출, 쿼리 이름으로 사용한다던가 등이 가능

Native Query

  • SQL 쿼리 실행하기
  • https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#sql
    @PersistenceContext // jpa 가장 핵심적인 빈
    EntityManager entityManager;

    @Override
    public void run(ApplicationArguments args) {
        List<Post> posts = entityManager
                .createNativeQuery("SELECT * FROM Post", Post.class)
                .getResultList();
        posts.forEach(System.out::print);
    }

실행결과

Hibernate: 
    SELECT
        * 
    FROM
        Post
Post{id=1, title='Jpa 공부중...}Post{id=2, title='Jpa 공부중...}





© 2019. by jaeuk