본문 바로가기
백엔드/Spring

[JPA] Collection 컬렉션 (Collection, List, Set, List+@OrderColumn)

by 작은소행성 2022. 9. 15.

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 프로그래밍

반응형