springframework/Spring Data JPA

Query

Jungsoomin :) 2020. 11. 13. 23:58

JPQL , HQL

  • JPQL : Java Persistence Query Language
  • HQL : Hibernate Query Language
  • SQL 과 비슷하나 큰 차이점Entity 기준으로 질의를 한다는 것

  • select 다음의 p 는 Entity 를 의미하며, FROM 절 뒤의 이름은 테이블이아니라 Entity 명으로 기입한다.
@Component
@Transactional
public class JpaParentChileRunner implements ApplicationRunner {

    @PersistenceContext
    private EntityManager entityManager;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        //JPA 2.0 이전에는 TypedQuery 생성이 불가했다. 이후에는 변환없이 바로 결과를 얻을 수 있다.
        TypedQuery<Post> query = entityManager.createQuery("SELECT p FROM Post as p",Post.class);
        List<Post> posts = query.getResultList();

        posts.forEach(System.out::println);

    }
}

JPQL, HQL 은 데이터베이스 독립적이며, JPQL, HQL 이 데이터베이스에 맞는 SQL 로 변환되어 실행된다.

Hibernate: 
    select
        post0_.id as id1_2_,
        post0_.title as title2_2_ 
    from
        post post0_
Post{id=18, title='Spring Data JPA 언제 보나.'}

toString() 메서드에 참조되는 Entity도 출력할 경우 JPA 는 해당 Entity 가 필요한 것으로 판단하어 추가 쿼리를 질의하게 되니 주의

@Entity
public class Post {

    @Id
    @GeneratedValue
    private Long id;

    private String title;

    // Entity 를 관리할 때 참조하는 Comment Entity 도 Persistent 상태로 관리해주렴.
    @OneToMany(mappedBy = "post", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
    private Set<Comment> comments = new HashSet<>();

    public void addComment(Comment comment) {
        comments.add(comment);
        comment.setPost(this);
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Set<Comment> getComments() {
        return comments;
    }

    public void setComments(Set<Comment> comments) {
        this.comments = comments;
    }

    @Override
    public String toString() {
        return "Post{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", comments=" + comments +
                '}';
    }
}

DDL = toString() 으로 출력해야할 Comment Entity 에 대해 추가 질의를 하는 모습

Hibernate: 
    Select
        * 
    from
        Post
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=?
Post{id=18, title='Spring Data JPA 언제 보나.', comments=[me.soomin.datajpa.domain.Comment@7a0f244f, me.soomin.datajpa.domain.Comment@3bfc6a5e]}

NativeQuery

  • createNativeQuery() 에 정의, 타입에 맞출 수 있음
  • 리턴 값은 제네릭이 아니기 때문에 제네릭 선언이 필요
@Component
@Transactional
public class JpaParentChileRunner implements ApplicationRunner {

    @PersistenceContext
    private EntityManager entityManager;
    @Override
    public void run(ApplicationArguments args) throws Exception {

        List<Post> posts = entityManager.createNativeQuery("Select * from Post", Post.class).getResultList();

        posts.forEach(System.out::println);
    }
}

DDL = 네이티브 쿼리에 의해 SQL 문으로 질의 된다.

Hibernate: 
    Select
        * 
    from
        Post
Post{id=18, title='Spring Data JPA 언제 보나.'}