4-1. ManyToOne
- 연관관계란?
- 서로 다른 두 객체가 연관성을 가지고 관계를 맺는 것
- 연관 관계의 분류
- 방향(Direction)에 따른 분류
- 참조에 의한 객체의 연관 관계는 단방향
- 테이블의 연관 관계는 외래 키를 이용하여 양방향 연관 관계의 특징을 가짐
- 객체간의 인과 관계를 양방향으로 만들고 싶을 경우 반대 쪽에서도 필드를 추가해서 참조를 보관
- 하지만 엄밀하게 이는 양방향 관계가 아니라 단방향 관계 2개로 볼 수 있음
- 다중성(Multiplicity)에 대한 분류
- 연간 관계가 있는 객체 관계 혹은 테이블 관계에서 실제로 연관을 가지는(매핑되는) 객체의 수 또는 행의 수에 따라 분류
- 1:1(OneToOne)
- 1:N(OneToMany)
- N:1(ManyToOne)
- N:N(ManyToMany)
- 연관 관계를 가지는 엔티티 조회 방법
- 객체 그래프 탐색(객체 연관관계를 사용한 조회)
- 객체 지향 쿼리 사용(JPQL)
@Entity(name="many_to_one_menu_and_category")
@Table(name="TBL_MENU")
public class MenuAndCategory {
@Id
@Column(name="MENU_CODE")
private int menuCode;
@Column(name="MENU_NAME")
private String menuName;
@Column(name="MENU_PRICE")
private int menuPrice;
@JoinColumn(name="CATEGORY_CODE")
@ManyToOne(cascade=CascadeType.PERSIST)
private Category category;
@Column(name="ORDERABLE_STATUS")
private String orderableStatus;
@Test
public void 다대일_연관관계_객체_그래프_탐색을_이용한_조회_테스트() {
int menuCode = 15;
MenuAndCategory foundMenu = entityManager.find(MenuAndCategory.class, menuCode);
Category menuCategory = foundMenu.getCategory();
assertNotNull(menuCategory);
System.out.println("menuCategory = " + menuCategory);
}
@Test
public void 다대일_연관관계_객체지향쿼리_사용한_카테고리_이름_조회_테스트() {
String jpql = "SELECT C.categoryName FROM many_to_one_menu_and_category M JOIN M.category C WHERE M.menuCode=15";
String category = entityManager.createQuery(jpql, String.class).getSingleResult();
assertNotNull(category);
System.out.println("category = " + category);
}
@Test
public void 다대일_연관관계_객체_삽입_테스트() {
MenuAndCategory menuAndCategory = new MenuAndCategory();
menuAndCategory.setMenuCode(999);
menuAndCategory.setMenuName("죽방멸치빙수");
menuAndCategory.setMenuPrice(30000);
Category category = new Category();
category.setCategoryCode(333);
category.setCategoryName("신규카테고리");
category.setRefCategoryCode(null);
menuAndCategory.setCategory(category);
menuAndCategory.setOrderableStatus("Y");
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
entityManager.persist(menuAndCategory);
entityTransaction.commit();
MenuAndCategory foundMenu = entityManager.find(MenuAndCategory.class, 999);
assertEquals(999, foundMenu.getMenuCode());
assertEquals(333, foundMenu.getCategory().getCategoryCode());
}
4-2. OneToMany
@Entity(name="one_to_many_category_and_menu")
@Table(name="TBL_CATEGORY")
public class CategoryAndMenu {
@Id
@Column(name="CATEGORY_CODE")
private int categoryCode;
@Column(name="CATEGORY_NAME")
private String categoryName;
@Column(name="REF_CATEGORY_CODE")
private Integer refCategoryCode;
@JoinColumn(name="CATEGORY_CODE")
@OneToMany(cascade=CascadeType.PERSIST)
private List<Menu> menuList;
@Test
public void 일대다_연관관계_객체_그래프_탐색을_이용한_조회_테스트() {
int categoryCode = 10;
CategoryAndMenu categoryAndMenu = entityManager.find(CategoryAndMenu.class, categoryCode);
assertNotNull(categoryAndMenu);
System.out.println(categoryAndMenu);
}
@Test
public void 일대다_연관관계_객체_삽입_테스트() {
CategoryAndMenu categoryAndMenu = new CategoryAndMenu();
categoryAndMenu.setCategoryCode(888);
categoryAndMenu.setCategoryName("일대다추가카테고리");
categoryAndMenu.setRefCategoryCode(null);
List<Menu> menuList = new ArrayList<>();
Menu menu = new Menu();
menu.setMenuCode(777);
menu.setMenuName("일대다아이스크림");
menu.setMenuPrice(50000);
menu.setOrderableStatus("Y");
menu.setCategoryCode(categoryAndMenu.getCategoryCode());
menuList.add(menu);
categoryAndMenu.setMenuList(menuList);
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
entityManager.persist(categoryAndMenu);
entityTransaction.commit();
CategoryAndMenu foundMenu = entityManager.find(CategoryAndMenu.class, 888);
System.out.println(foundMenu);
}
4-3. BiDirection
- 양방향 연관관계 매핑
- 데이터베이스의 테이블은 외래키 하나로 양방향 조회 가능
- 객체는 서로 다른 두 단방향 참조를 합쳐서 양방향
- 두 개의 연관 관계 중 관계의 주인을 정하고, 주인이 아닌 연관 관계를 하나 더 추가하는 방식으로 진행
- 반대 방향으로도 access함
- 객체 그래프 탐색을 할 일이 많은 경우 양방향 연관관계 매핑 사용
- 연관 관계의 주인을 정하는 기준
- 비즈니스 중요도를 배제하고 단순히 외래키 관리자의 의미 부여
- 외래키를 가지고 있는 엔티티가 연관 관계의 주인
@Entity(name="bidirection_menu")
@Table(name="TBL_MENU")
public class Menu {
@Id
@Column(name="MENU_CODE")
private int menuCode;
@Column(name="MENU_NAME")
private String menuName;
@Column(name="MENU_PRICE")
private int menuPrice;
@JoinColumn(name="CATEGORY_CODE")
@ManyToOne
private Category category;
@Column(name="ORDERABLE_STATUS")
private String orderableStatus;
@Entity(name="bidirection_category")
@Table(name="TBL_CATEGORY")
public class Category {
@Id
@Column(name="CATEGORY_CODE")
private int categoryCode;
@Column(name="CATEGORY_NAME")
private String categoryName;
@Column(name="REF_CATEGORY_CODE")
private Integer refCategoryCode;
@OneToMany(mappedBy="category")
private List<Menu> menuList;
@Test
public void 양방향_연관관계_매핑_조회_테스트() {
int menuCode = 10;
int categoryCode = 10;
Menu foundMenu = entityManager.find(Menu.class, menuCode);
Category foundCategory = entityManager.find(Category.class, categoryCode);
assertEquals(menuCode, foundMenu.getMenuCode());
assertEquals(categoryCode, foundCategory.getCategoryCode());
System.out.println(foundMenu);
System.out.println(foundCategory);
System.out.println(foundCategory.getMenuList());
}
@Test
public void 양방향_연관관계_주인_객체를_이용한_삽입_테스트() {
Menu menu = new Menu();
menu.setMenuCode(125);
menu.setMenuName("연관관계주인메뉴");
menu.setMenuPrice(10000);
menu.setOrderableStatus("Y");
menu.setCategory(entityManager.find(Category.class, 4));
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
entityManager.persist(menu);
entityTransaction.commit();
Menu foundMenu = entityManager.find(Menu.class, menu.getMenuCode());
assertEquals(menu.getMenuCode(), foundMenu.getMenuCode());
System.out.println(foundMenu);
}
@Test
public void 양방향_연관관계_주인이_아닌_객체를_이용한_삽입_테스트() {
Category category = new Category();
category.setCategoryCode(1004);
category.setCategoryName("양방향 카테고리");
category.setRefCategoryCode(null);
EntityTransaction entityTransaction = entityManager.getTransaction();
entityTransaction.begin();
entityManager.persist(category);
entityTransaction.commit();
Category foundCategory = entityManager.find(Category.class, category.getCategoryCode());
assertEquals(category.getCategoryCode(), foundCategory.getCategoryCode());
System.out.println(foundCategory);
}
}