728x90
1.도달 가능성(reachability)
도달 가능성은 객체가 영속성 컨텍스트에 포함될 수 있는지를 결정하는 개념이다.
즉, 영속화될 자격이 생긴다는거다.(영속화되는게 아니라 자격이 생긴다는것)
객체 간의 참조 관계에 의해 한 객체가 다른 객체를 참조하고 있으면, 참조된 객체는 도달 가능하게되고 도달 가능한 객체는 영속성 컨텍스트에 의해 관리되며, 데이터베이스와의 동기화가 이루어진다.
만약 다음 같은 3개의 객체가 있다고 볼때, 지금 Aricle은 Board와 Member 객체를 참조관계로 가지고있다.
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL)
private List<Article> articles;
}
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "board_id")
private Board board;
@ManyToOne
@JoinColumn(name = "author_id")
private Member author;
}
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
여기서 다음코드를 실행하게 되면 Article 객체가 board와 author 객체를 각각 참조하고 있기 때문에, 이 두 객체는 도달 가능하게 되어, 영속성 컨텍스트에서 관리될 수 있다.
Article article = entityManager.find(Article.class, id);
하지만 이때 이때 Member와 Board 둘다 영속화 된다는건 아니다.
Board는 cascade = CascadeType.ALL로 설정되있어서 Article이 영속화되면 Board 객체의 articles 리스트도 갱신된다.
즉 Article객체가 영속화될때 연결된 Board 객체도 자동으로 영속화 되는거다.
(Board 객체가 영속화될때는 포함된 Article 객체들도 영속화됨)
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL)
private List<Article> articles;
하지만 Member은 ManyToOne 관계로 연결되어 이 관계에서 Member 객체는 부모 객체인 Article 객체에 의해 참조되고 있다. 즉, Article 객체가 영속화될 때, Member 객체는 자식 객체로서 Article에 연관된 객체일 뿐, 자동으로 영속화되지는 않는다.
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "author_id")
private Member author;
}
이러면 문제가 발생할수 있다.
만약 다음과같은 코드 구조가 있다고 할때 articleRepository.save(article)을 할때 Article은 영속화되는데 author은 영속화되지않는다.
author 필드에 Member 객체를 지정하고 저장하고싶은데 Member 객체는 데이터베이스에 존재하지 않아서 그대로 오류로 이어진다.
Member author = new Member();
Article article = new Article();
article.setAuthor(author);
articleRepository.save(article);
만약 author에 CascadeType.PERSIST로 설정해서 도달 가능하게 만든다면 Article 객체가 영속화될때 Member 객체도 자동으로 영속화된다.
그러면 위의 코드에서 author는 자동으로 영속화되어 Member 테이블에 저장되고, 그뒤 Article또한 table에 저장된다.
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "author_id")
private Member author;
2.영속성 전이(Persistence Cascade)
JPA에서 연관된 엔티티들이 저장, 수정, 삭제 등의 영속성 상태 변경 작업을 할 때, 연관된 다른 객체에도 자동으로 동일한 작업을 적용하는것이다. CascadeType를 통해 설정할수있다.
PERSIST | 부모 엔티티가 영속화될 때 연관된 자식 엔티티도 영속화 |
MERGE | 부모 엔티티가 병합될 때 연관된 자식 엔티티도 병합 |
REMOVE | 부모 엔티티가 삭제될 때 연관된 자식 엔티티도 삭제 |
REFRESH | 부모 엔티티가 새로고침될 때 연관된 자식 엔티티도 새로고침 |
DETACH | 부모 엔티티가 분리될 때 연관된 자식 엔티티도 분리 |
ALL | 위의 모든 작업이 연관된 자식 엔티티에 전파 |
3.고아 객체(orphan entity)
부모 엔티티와의 연관관계가 끊어진 자식 엔티티이다. 부모가 자식을 참조하는 List에서 자식을 제거하면, 그 자식은 더 이상 어디에도 속하지 않게되는거다.
이 코드에서 다음처럼 board의 Article 리스트에서 특정 Article을 그냥 remove로 없애고 커밋해버리면,
빠져버린 Article은 DB에 계속 남아있지만 부모없는 고아가 되버린다. 즉 Board에는 Article이 없다고 되어있는데 DB에 Article이 남아있는것이다. 하지만 Article가 Board없이 독립적으로 존재하지않기에 이는 옳지않다.
(게시글의 생명주기는 게시판에 종속됨)
@Entity
public class Board {
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL)
private List<Article> articles = new ArrayList<>();
}
@Entity
public class Article {
@ManyToOne
@JoinColumn(name = "board_id")
private Board board;
}
Article article = board.getArticles().get(0);
board.getArticles().remove(article);
orphanRemoval = true를 사용하면 위의 remove로 리스트에서 지우고 커밋을 하면 해당 자식 엔티티를 자동으로 DB에서 삭제해준다.
(이때 영속 상태여야 적용됨)
public class Board {
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Article> articles;
}
728x90
'BackEnd > SpringBoot' 카테고리의 다른 글
[SpringBoot] websocket 채팅방 이미지 업로드하기 (0) | 2025.05.31 |
---|---|
[SpringBoot] STOMP WebSocket 1:1 메시징 사용자별 구독관리 (0) | 2025.05.29 |
[SpringBoot] ORM, JPA, 영속성에 대해 (1) | 2025.05.27 |