๐ŸŒฑ JPA - Cascade ๋…ธํŠธ


JPA์—์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅํ•  ๋•Œ ์—ฐ๊ด€๋œ ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ๋Š” ์˜์† ์ƒํƒœ์—ฌ์•ผ ํ•œ๋‹ค.
๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜์† ์ƒํƒœ๋กœ ๋งŒ๋“ค ๋•Œ ์—ฐ๊ด€๋œ ์ž์‹๋„ ํ•œ๋ฒˆ์— ์˜์† ์ƒํƒœ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

Cascade๋ž€?

  • ์˜์†์„ฑ ์ „์ด
  • ์—ฐ๊ด€๊ด€๊ณ„์— ์žˆ๋Š” ์—”ํ‹ฐํ‹ฐ์— ์ž‘์—…์ด ์ด๋ฃจ์–ด์ ธ ์ƒํƒœ ๋ณ€ํ™”๊ฐ€ ์ด๋ค„์งˆ ์‹œ ๋™์ผํ•œ ์ž‘์—…์ด ์—ฐ๊ฒฐ๋œ ์—”ํ‹ฐํ‹ฐ์— ์ „์ด๋˜๋Š” ์˜ต์…˜
  • ์ผ๋ฐ˜์ ์œผ๋กœ ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ์—์„œ cascade ์˜ต์…˜์„ ๊ฑธ์–ด์คŒ
  • ์ž์‹์—์„œ ๋ถ€๋ชจ๋กœ ์˜ต์…˜์„ ๊ฑฐ๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค๊ณ ํ•จ
  • ์ฆ‰์‹œ๋กœ๋”ฉ, ์ง€์—ฐ๋กœ๋”ฉ, ์—ฐ๊ด€๊ด€๊ณ„ ์„ธํŒ…๊ณผ ๊ด€๊ณ„ ์—†์Œ
  • ๋ถ€๋ชจ, ์ž์‹ ์—”ํ‹ฐํ‹ฐ์™€ ์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์ธ(์™ธ๋ž˜ํ‚ค ๊ด€๋ฆฌ์ž)๋Š” ๋‹ค๋ฆ„

Entity์˜ ์ƒํƒœ

  • Transient : JPA๊ฐ€ ๋ชจ๋ฅด๋Š” ์ƒํƒœ (๋‹จ์ˆœ ๊ฐ์ฒด ์ƒ์„ฑ)
  • Persistent : JPA๊ฐ€ ๊ด€๋ฆฌ์ค‘์ธ ์ƒํƒœ (1์ฐจ ์บ์‹œ, Dirty Checking, Write Behind, โ€ฆ)
  • Detached : JPA๊ฐ€ ๋”์ด์ƒ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ
  • Removed : JPA๊ฐ€ ๊ด€๋ฆฌํ•˜๊ธด ํ•˜์ง€๋งŒ ์‚ญ์ œํ•˜๊ธฐ๋กœ ํ•œ ์ƒํƒœ

casecade ์˜ต์…˜ (์ผ๋ถ€)

PERSIST

  • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜์†ํ™” ํ•  ๋•Œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์œ ์ง€
  • Transient ์ธ์Šคํ„ด์Šค๋ฅผ Persistent๋กœ ๋งŒ๋“ค์–ด์คŒ

REMOVE

  • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ญ์ œํ•  ๋•Œ, ์—ฐ๊ด€๋œ ์—”ํ‹ฐ๋„ ํ•จ๊ป˜ ์‚ญ์ œ

ALL

  • ๋ชจ๋“  CASCADE ์˜ต์…˜ ์ ์šฉ
  • ๋ชจ๋“  ์ž‘์—…์„ ๋ถ€๋ชจ์—์„œ ์ž์‹ ์—”ํ‹ฐํ‹ฐ๋กœ ์ „ํŒŒ

์˜ˆ์‹œ

์•„๋ฌด๋Ÿฐ ์˜ต์…˜์ด ์—†๋Š” ๊ฒฝ์šฐ

Comment

@Entity
public class Comment {

    @Id
    @GeneratedValue
    private Long id;
    private String comment;

    @ManyToOne
    private Post post;
} 

Post

@Entity
public class Post {

    @Id
    @GeneratedValue
    private Long id;
    private String title;

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

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

Test ์ฝ”๋“œ

  • ์ž์‹์ธ Comment๋Š” ์ €์žฅ๋˜์ง€ ์•Š์Œ
    • id๊ฐ€ null์ž„์„ ํ™•์ธ

CascadeType.ALL์„ ๊ฑด ๊ฒฝ์šฐ

  • ๋ถ€๋ชจ์ธ Post ์—”ํ‹ฐํ‹ฐ์—์„œ ์ž์‹์ธ Comments์— ์˜ต์…˜๊ฑธ๊ธฐ

  • id๊ฐ€ null์ด ์•„๋‹˜์„ ํ™•์ธ

๊ณ ์•„ ๊ฐ์ฒด ์ œ๊ฑฐ

  • JPA์—์„œ๋Š” ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ์™€ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ๋Š์–ด์ง„ ์ž์‹ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ž๋™์œผ๋กœ ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋Šฅ ์ œ๊ณต
  • ์ฐธ์กฐ๊ฐ€ ์ œ๊ฑฐ๋œ ์—”ํ‹ฐํ‹ฐ๋Š” ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ฐธ์กฐํ•˜์ง€ ์•Š๋Š” ๊ณ ์•„ ๊ฐ์ฒด๋กœ ๋ณด๊ณ  ์‚ญ์ œ
  • ๋•Œ๋ฌธ์— ์ฐธ์กฐํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ํ•˜๋‚˜์ผ ๋•Œ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•จ (ํŠน์ • ์—”ํ‹ฐํ‹ฐ์—์„œ๋งŒ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋Š” ์—”ํ‹ฐํ‹ฐ)
  • @OneToOne, @OneToMany ์—์„œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Example

  • Comments ๊ฐ์ฒด๋Š” Post์—์„œ๋งŒ ์†Œ์œ ํ•˜๊ณ  ์žˆ์Œ
  • Comments์— orphanRemoval ์˜ต์…˜ ์ถ”๊ฐ€

  • Comments๋ฅผ ์ œ๊ฑฐํ•˜์˜€์„ ๋•Œ,

  • comment์— ๋Œ€ํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด delete ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ

์ฐธ๊ณ  ์ž๋ฃŒ