JPA는 자바에서 기본적으로 제공하는 Collection, List, Set, Map 컬렉션을 지원한다.
하이버네이트가 컬렉션을 효율적으로 관리하기 위해 하이버네이트는 엔티티를 영속 상태로 만들 때 Collection으로 한번 감싸서 사용한다.
Collection은 아래 두가지 상황에서 사용한다.
- @OneToMany , @ManyToMany 를 사용해서 일대다나 다대다 관계를 매핑할 때
- @ElementCollection 을 사용해서 값 타입을 하나 이상 보관할 때
Collection, List
- Collection, List 는 중복을 허용하는 컬렉션이다.
- PersistentBag을 래퍼 컬렉션으로 사용한다.
- 하이버네이트의 특징 때문에 Collection을 사용할 때 즉시 초기화해서 사용하는 것을 권장한다.
- 해당 인터페이스는 ArrayList로 초기화 한다.
@Entity
public class Parent{
@Id
@GeneratedValue
private Long id;
@OneToMany
@JoinColumn
private Collection<CollectionChild> collection = new ArrayList<CollectionChild>();
@OneToMany
@JoinColumn
private List<ListChild> list = new ArrayList<ListChild>();
}
Collection, List 는 엔티티를 추가할 때 중복된 엔티티가 있는지 비교하지 않고 단순히 저장만 하면 된다.
중복을 허용하는 특성때문에 객체를 추가할 때 지연로딩이 발생하지 않기 때문에 엔티티를 추가해도 지연 로딩된 컬렉션을 초기화하지 않는다.
엔티티가 있는지 체크하거나 삭제할 경우 equals로 비교해야 하므로 지연로딩이 발생한다.
List<Comment< comments = new ArrayList<Comment>();
// 단순 추가, 결과는 항상 true
boolean result = comments.add(data)
comments.contains(comment); // equals 비교
comments.remove(comment); // equals 비교
Set
- PersistentSet을 래퍼 컬렉션으로 사용한다.
- 해당 인터페이스는 HashSet으로 초기화하면 된다.
- HashSet은 중복을 허용하지 않으므로 add()메소드로 객체를 추가할 때 마다 equals()메소드로 같은 객체가 있는지 비교한다.
@Entity
public class Parent{
@OneToMany
@JoinColumn
private Set<SetChild> set = new HashSet<SetChild>();
}
Set은 엔티티를 추가할 때 중복된 엔티티가 있는지 비교하고
엔티티를 추가할 때 지연 로딩된 컬렉션을 초기화 한다.
Set<Comment< comments = new HashSet<Comment>();
boolean result = comments.add(data) // hashcode + equals 비교
comments.contains(comment); // hashcode + equals 비교
comments.remove(comment); // hashcode + equals 비교
List + @OrderColumn
- PersistentList를 래퍼 컬렉션으로 사용한다.
- OrderColumn을 추가하면 순서가 있는 특수한 컬렉션으로 인식하는데, 순서를 사용하는 것은 데이터베이스에서 값을 저장해서 조회할 때 사용하기 위함이다.
@Entity
public class Board{
@Id
@GeneratedValue
private Long id;
private String title;
private String content;
@OneToMany(mappedBy = "board")
@OrderColumn(name = "POSITION")
private List<Comment> comments = new ArrayList<Comment>();
}
- @OrderColumn(name = "POSITION")
- List의 위치 값을 테이블의 POSITION 컬럼에 보관
- 일대다 관계여서 다쪽에 저장함
@Entity
public class Comment{
@Id
@GeneratedValue
private Long id;
private String comment;
@ManyToOne
@JoinColumn(name = "BOARD_ID")
private Board board;
}
@OrderColumn 사용 코드
Board board = new Board("제목1", "내용1");
em.persist(board);
Comment comment1 = new Comment("댓글1");
comment1.setBoard(board);
board.getComments().add(comment1); // POSITION 0
em.persist(comment1);
Comment comment2 = new Comment("댓글2");
comment2.setBoard(board);
board.getComments().add(comment2); // POSITION 1
em.persist(comment2);
Comment comment3 = new Comment("댓글3");
comment3.setBoard(board);
board.getComments().add(comment3); // POSITION 2
em.persist(comment3);
Comment comment4 = new Comment("댓글4");
comment4.setBoard(board);
board.getComments().add(comment4); // POSITION 3
em.persist(comment4);
하이버네이트 내장 컬렉션과 특징
컬렉션 인터페이스 | 내장 컬렉션 | 중복 허용 | 순서 보관 |
Collection, List | PersistentBag | O | X |
Set | PersistentSet | X | X |
List +@OrderColumn | PersistentList | O | O |
참고
[Book] 자바 ORM 표준 JPA 프로그래밍
반응형
'공부 > Spring' 카테고리의 다른 글
[Spring Security] The signing key's size is 40 bits which is not secure enough for the HS512 algorithm. (0) | 2022.11.09 |
---|---|
[spring] swagger2로 API 명세서 만들기 (0) | 2022.09.28 |
[JPA] Optional (0) | 2022.09.14 |
[JPA] @Embedded, @Embeddable (0) | 2022.09.14 |
[JPA] 최범균님 <JPA 기초> 내용 정리하기 (0) | 2022.09.07 |