객체 관계 맵핑


객체 관계 맵핑이라고하는 ORM에서 가장 까다로운 부분은 연관관계를 매핑하는 것

연관 관계

서로 다른 두 객체가 연관성을 가지고 관계를 맺는 것

 

1. 방향(Direction)에 따른 분류
참조에 의한 객체의 연관 관계는 단방향이다. 테이블의 연관 관계는 외래 키를 이용하여 양방향 연관 관계의 특징을 가진다.
객체 간의 연관 관계를 양방향으로 만들고 싶을 경우 반대 쪽에서도 필드를 추가해서 참조를 보관하면 된다.
하지만 엄밀하게 이는 양방향 관계가 아니라 단 방향 관계 2개로 볼 수 있다.
1-1. 단방향 연관 관계
1-2. 양방향 연관 관계

 

2. 다중성(Multiplicity)에 대한 분류
연관 관계가 있는 객체 관계 혹은 테이블 관계에서 실제로 연관을 가지는 (매핑되는) 객체의 수 또는 행의 수에 따라 분류된다.
2-1. 1:1(One To One) 연관 관계
2-1. 1:N(One To Many) 연관 관계
2-1. N:1(Many To One) 연관 관계
2-1. N:N (Many To Many) 연관 관계


 

@JoinColumn

 

일반적인 컬럼이 아니라 외래키를 매핑할 떄 사용

 

referenceColumnName

 

일반적인 컬럼이 아니라 외래키를 매핑할 떄 사용

 

foreignKey

 

 외래키 제약 조건을 직접 지정 할 수 있으며 테이블 생성시 사용 된다.

 

unique, nullable, insertable, updatable, columnDefinition, table

 

@Column의 속성과 동일

 

@ManyToOne

 

다대일 관계에서 사용

 

cascade 

 

영속성 전이 기능을 사용한다. (연관 된 엔티티를 함께 영속성으로 관리한다는 의미)

 

orphanRemoval

 

true로 설정하면 고아 객체 제거

 


	@JoinColumn(name="CATEGORY_CODE")
	@ManyToOne(cascade=CascadeType.PERSIST)
	private Category category;

Category 클래스와 관련된 데이터를 저장하는 MenuAndCategory 클래스의 일부이다.

 

1.Category 클래스의 인스턴스와 관련된 데이터를 저장하기 위해 @ManyToOne 어노테이션을 사용하고

2.@JoinColumn 어노테이션은 연결하는 컬럼의 이름을 정의한다. 위의 코드에서는 "CATEGORY_CODE" 컬럼과 연결되어 있으므로, 해당 컬럼이 존재해야 한다.

3.@ManyToOne 어노테이션은 Many-to-One 관계를 정의한다. 위의 코드에서는 Menu 클래스와 Category 클래스 간의 Many-to-One 관계를 정의한다. CascadeType.PERSIST 옵션은 연관 엔티티를 영구 저장할 때 해당 엔티티의 연관 엔티티도 함께 저장하도록 하는 것이다.

 

PERSIST

따라서 위의 코드에서는 Menu 클래스의 category 필드가 Category 클래스의 인스턴스를 참조하며,

해당 인스턴스를 영구 저장할 때 연관 엔티티도 함께 저장되게 된다.

 

CATEGORY_CODE을 다대일 연관 관계를 가지게 하여서 조회하도록 한다.

 

그럼 이전과는 다르게 다대일 연관 관계 객체지향 쿼리를 사용한 카테고리 이름 조회를 진행하려고 하면

join문법이 다소 sql과는 차이가 잇지만, 직접 쿼리를 작성할 수 있는 문법을 제공한다.

여기서 주의할 점은 FROM절에 기술할 테이블명에는 반드시 텐티티명이 작성되어야 한다는 점이다.

 

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 = 일식이 나오게 된다.

		assertNotNull(category);
		System.out.println("category = " + category);

그럼 다대일 연관관계 객체 삽입은 어떻게 될까?

다대일 연관관계를 등록하였던 MenuAndCategory 클래스의 인스턴스를 생성하는 것

		MenuAndCategory menuAndCategory = new MenuAndCategory();
		menuAndCategory.setMenuCode(99999);
		menuAndCategory.setMenuName("죽방멸치빙수");
		menuAndCategory.setMenuPrice(30000);
		
		Category category = new Category();
		category.setCategoryCode(33333);
		category.setCategoryName("신규카테고리");
		category.setRefCategoryCode(null);
        
       	     menuAndCategory.setCategory(category);
		menuAndCategory.setOrderableStatus("Y");

 

commit을 할 경우 flush 하며 컨텍스트 내의 영속성 객체를 insert 하는 쿼리를 동작시키는데 
부모 테이블(TBL_CATEGORY)에 값이 먼저 들어있어야 자식 테이블(TBL_MENU)에 데이터를 넣을 수 있다.
@ManyToOne 어노테이션에 영속성 전이 설정을 해주어야 한다.

 


 

이제는 좀 색다르게 List형식으로 menu에 있는 음식들을 List로 뽑게 정의하면!

	@JoinColumn(name="CATEGORY_CODE")
	@OneToMany(cascade=CascadeType.PERSIST)
	private List<Menu> menuList;

누르기

더보기

CategoryAndMenu [categoryCode=10, categoryName=기타, refCategoryCode=2, menuList=[Menu [menuCode=2, menuName=우럭스무디, menuPrice=5000, categoryCode=10, orderableStatus=Y], Menu [menuCode=3, menuName=생갈치쉐이크, menuPrice=6000, categoryCode=10, orderableStatus=Y], Menu [menuCode=11, menuName=정어리빙수, menuPrice=10000, categoryCode=10, orderableStatus=Y], Menu [menuCode=12, menuName=날치알스크류바, menuPrice=2000, categoryCode=10, orderableStatus=Y], Menu [menuCode=17, menuName=아이스가리비관자육수, menuPrice=6000, categoryCode=10, orderableStatus=Y]]]

이렇게 리스트가 쭉 뽑혀서 나오게 된다!



 

영속성 전이


특정 엔티티를 영속화할 때 연관된 엔티티도 함께 영속화 한다는 의미

 

CascadeType.PERSIST

cascade=CascadeType.PERSIST를 설정하면 Menu를 저장하기 전에 Category부터 저장하게 된다.

 

 

다음 포스팅에서 계속 되기

 

SMALL

+ Recent posts