Programming/Spring Data JPA

JPA 프로그래밍 - 2 (스프링 데이터 JPA - 3)

흠냐아뤼 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