ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JPA 프로그래밍 - 2 (스프링 데이터 JPA - 3)
    Programming/Spring Data JPA 2021. 1. 1. 15:46
    728x90

     

    1. Entity 상태

     

    - Transient : JPA가 모르는 상태

    - Persistent : JPA가 관리중인 상태 (1차 캐시, Dirty Checking, Write Behind, ...) - save

    - Detached : JPA가 더이상 관리하지 않는 상태 - return 한 경우

    - Removed : JPA가 관리하긴 하지만 삭제하기로 한 상태

     

    save()를 호출한다고 바로 DB에 반영되는 것이 아님, JPA가 판단하여 DB에 반영 

     

     

    2. Cascade

    엔티티의 상태 변화를 전파 시키는 옵션

     

    Parent - Child 구조를 만들고 양방향 관계를 만듬

    - Post.java

    cascade를 통해 상태 변화시 저장된 Comment에게 전파하겠다는 설정을 함

    @Entity
    public class Post {
    
        @Id @GeneratedValue
        private Long id;
    
        private String title;
    
        @OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
        private Set<Comment> comments = new HashSet<>();
    
        public void addComment(Comment comment) {
            this.getComments().add(comment);
            comment.setPost(this);
        }
    }
    

     

    - Comment.java

    @Entity
    public class Comment {
    
        @Id @GeneratedValue
        private Long id;
    
        private String comment;
    
        @ManyToOne
        private Post post;
    }
    

     

    - JpaRunner.java

    Post가 save를 통해 Persistent 상태로 바뀌면, Comment 들도 상태가 바뀜 -> save를 하지 않은 comment들도 DB에 반영됨

    @Component
    @Transactional
    public class JpaRunner implements ApplicationRunner {
    
        @PersistenceContext
        EntityManager entityManager;
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            Post post = new Post();
            post.setTitle("This is Title");
    
            Comment comment = new Comment();
            comment.setComment("comment");
            post.addComment(comment);
    
            Comment comment1 = new Comment();
            comment1.setComment("comment1");
            post.addComment(comment1);
    
            Session session = entityManager.unwrap(Session.class);
            session.save(post);
        }
    }
    

     

     

    2. Fetch

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

    - @OneToMany의 기본값은 Lazy

    - @ManyToOne의 기본값은 Eager (쿼리가 한 번 일어남)

    *PK를 통한 쿼리에만 Fetch 모드가 결정됨

     

    이를 잘 설정해야 성능을 최적화할 수 있음

    필요 없는 값을 메모리에 너무 많이 올려놓으면 성능 문제 발생

     

     

    3. Query

    *항상 하이버네이트가 내가 의도한 쿼리를 하는지 살펴보기 - 의도하지 않는 쿼리는 성능 문제 발생 가능*

     

    JPQL (HQL)

    - SQL과 비슷하지만, 엔테티 기준으로 작성해야 함

    - JPA 또는 하이버네이트가 해당 쿼리를 SQL로 변환해서 실행함

    TypedQuery<Post> query = entityManager.createQuery("SELECT p From Post As p", Post.class);
    List<Post> posts = query.getResultList();
    posts.forEach(System.out::);

     

    Criteria

    - JPQL 은 타입 세이프 하지 않음! (문자열이 들어가기 때문에)

    - 이는 타입 세이프 쿼리

     

    Native Query

    - SQL 쿼리 실행하기

    List<Post> posts = entityManager.createNativeQuery("SELECT * FROM POST", Post.class).getResultList();
    posts.forEach(System.out::println);

     

     

    4. 성능 문제를 예방하기 위해 SQL문 확인하기

    내가 예측한 대로 원하는 만큼 쿼리가 발생하는지?

    원하는 데이터를 적절한 타이밍에 가져오고 있는지?

     

    실행된 SQL문의 ? 값 확인하기

    logging.level.org.hibernate.type.descriptor.sql=trace

     

     

    인프런 백기선님 '스프링 데이터 JPA’ 강의를 듣고 정리한 내용입니다.
    728x90

    댓글

Designed by Tistory.