Spring/Spring Data JPA

[Spring Data JPA] 4. 엔터티 상태와 Cascade

미스터로즈 2021. 8. 22. 14:50

백기선님 강의 중 Spring Data JPA에 대해서 정리를 해놓은 블로그입니다.

자세한 내용은 강의를 참고해주세요.

강의 링크


Cascade 란?

엔터티의 상태 변화를 전파시키는 옵션입니다.

@OneToMany나 @ManyToOne에 옵션으로 줄 수 있는 값입니다.

 

만약 엔터티의 상태 변화가 있으면 연관되어 있는 엔터티에도 상태 변화를 전이시키는 옵션입니다.

 

 

Cascade 의 종류

  • CascadeType.PERSIST
    엔티티를 영속화 할 때이 필드에 보유 된 엔티티도 유지합니다. EntityManager가 flush 중에 새로운 엔티티를 참조하는 필드를 찾고이 필드가 CascadeType.PERSIST를 사용하지 않으면 오류이므로이 Cascade 규칙의 자유로운 적용을 제안합니다.

 

  • CascadeType.MERGE
    엔티티 상태를 병합 할 때, 이 필드에 보유 된 엔티티도 병합하십시오.

 

  • CascadeType.REFRESH
    엔티티를 새로 고칠 때, 이 필드에 보유 된 엔티티도 새로 고칩니다.

 

  • CascadeType.REMOVE
    엔티티를 삭제할 때, 이 필드에 보유 된 엔티티도 삭제하십시오.

 

  • CascadeType.DETACH
    부모 엔티티가 detach()를 수행하게 되면, 연관된 엔티티도 detach() 상태가 되어 변경사항이 반영되지 않는다.

 

  • CascadeType.ALL
    모든 Cascade 적용

엔터티의 상태

엔터티의 상태는 크게 4가지로 나눌수 있습니다.

1. Transient: 객체를 생성하고, 값을 주어도 JPA나 hibernate가 그 객체에 관해 아무것도 모르는 상태. 즉, 데이터베이스와 매핑된 것이 아무것도 없다.


2. Persistent: 저장을 하고나서, JPA가 아는 상태(관리하는 상태)가 된다. 그러나 .save()를 했다고 해서, 이 순간 바로 DB에 이 객체에 대한 데이터가 들어가는 것은 아니다. JPA가 persistent 상태로 관리하고 있다가, 후에 데이터를 저장한다.

(1차 캐시, Dirty Checking(변경사항 감지), Write Behind(최대한 늦게, 필요한 시점에 DB에 적용) 등의 기능을 제공한다)


3. Detached: JPA가 더이상 관리하지 않는 상태. JPA가 제공해주는 기능들을 사용하고 싶다면, 다시 persistent 상태로 돌아가야한다.


4. Removed: JPA가 관리하는 상태이긴 하지만, 실제 commit이 일어날 때, 삭제가 일어난다.

 

 


실습

 

Post 클래스 

    @Id @GeneratedValue
    private Long id;

    private String title;

    @OneToMany(mappedBy = "post")
    private Set<Comment> comments = new HashSet<Comment>();

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

+ 게터 세터

 

    @Id @GeneratedValue
    private Long id;

    private String comment;

    @ManyToOne
    private Post post;

+ 게터 세터

 

데이터 넣기

        Post post = new Post();
        post.setTitle("Spring Data JAP 언제 보나...");

        Comment comment = new Comment();
        comment.setComment("빨리 보고 싶어요");
        post.addComment(comment);

        Comment comment1 = new Comment();
        comment1.setComment("곧 보여드릴게요");
        post.addComment(comment1);

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

 

But, post만 넣었기 때문에 comment에는 아무것도 들어있지 않습니다.

 

 

    @Id @GeneratedValue
    private Long id;

    private String title;

    @OneToMany(mappedBy = "post" , cascade = CascadeType.PERSIST)
    private Set<Comment> comments = new HashSet<Comment>();

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

Cascade 옵션을 넣어줍니다. 그러면 자동으로 comment 까지 데이터를 넣어주게 됩니다.