ORM(Object Relational Mapping) : 객체관계 매핑
JPA :
조회한 데이터를 자바 객체로 개발자가 직접 변환을 해 주어야 한다.
이런 작업들은 마이바티스를 통해서 해결이 가능하다.
List<Menu> menuList = new ArrayList<>();
while(rset.next()) {
Menu menu = new Menu();
menu.setMenuCode(rset.getInt("MENU_CODE"));
menu.setMenuName(rset.getString("MENU_NAME"));
menu.setMenuPrice(rset.getInt("MENU_PRICE"));
menu.setCategoryCode(rset.getInt("CATEGORY_CODE"));
menu.setOrderableStatus(rset.getString("ORDERABLE_STATUS"));
menuList.add(menu);
}
2-2. 연관된 객체 문제
메뉴에 해당하는 카테고리의 이름을 함께 조회해야 한다는 요구사항이 변경되었다.
JPA는 데이터베이스에 저장하고 사용할 때 개발자가 직접 SQL문을 작성하지 않는다.
JPA가 제공하는 API를 사용하면 내부에서 SQL을 생성해서 동작을 시킨다.
따라서 SQL에 의존적이지 않게 된다. (의존하는 것은 직접 사용하지 않으면 의존성이 낮아지게 된다.)
또한 JPA를 사용하여 연관관계 객체를 매핑 설정 해두면 항시 연관된 객체도 함께 조회하기 때문에 사용하는 측에서 신뢰하고 사용할 수 있다.(NPE 발생하지 않음을 신뢰할 수 있음)
3-1. 상속 문제
객체지향언어의 상속 개념과 유사한 것이 데이터베이스의 서브타입엔터티 이다.
유사한 것 같지만 다른 부분은 데이터베이스의 상속은 상속 개념을 데이터로 추상화 하여 슈퍼타입과 서브타입으로 구분하고,
슈퍼타입의 모든 속성들을 서브타입이 공유하지 못하며 물리적으로도 다른 테이블로 분리가 된 형태이다. (설계에 따라 속성으로 추가되기도 함)
두 개 서로 다른 테이블을 조회하기 위해서는 공유하는(FK) 컬럼을 이용해 JOIN을 해서 사용해야 한다.
하지만 객체지향의 상속은 슈퍼타입의 속성을 공유해서 사용하기 때문에 여기서 패러다임 불일치 현상이 발생하게 된다.
또한 insert 시에는 각 테이블에 insert구문을 따로따로 실행시켜야 한다.
JPA는 상속과 관련된 패러다임의 불일치 문제를 개발자 대신에 해결해준다.
마치 컬렉션에 객체를 저장하듯 JPA에게 객체만 저장하면 된다.
3-2. 연관관계
객체지향에서 말하는 가지고 있는(assosication 연관 관계, 혹은 collection 연관 관계)경우 데이터베이스의 저장 구조와는 다른 형태이다.
따라서 이러한 패러다임 불일치 현상을 없애기 위한 개발자의 많은 노력이 필요하게 된다.
즉, 조인한 컬럼값들을 맞는 객체의 속성에 값을 대입하고 연관관계에 있는 객체도 속성으로 넣어주어야 한다.
만약 이러한 관계설정이 누락되는 경우 NPE가 발생할 가능성이 생기게 된다.
Menu menu = new Menu();
Category category = new Category();
menu.setCategory(category); //메뉴와 카테고리의 관계 설정.
하지만 JPA에서는 정말 간단하게 이 문제가 해결된다.
Menu menu = entityManager.find(Menu.class, menuCode);
Category category = menu.getCategory();
//연관객체를 함께 조인해서 조회하는 것이 보장된다. (NPE 발생하지 않음)
3-3. 객체 그래프 탐색
위와 같이 연관관계가 연이어서 여러 개의 객체간의 복잡한 관계가 형성이 된 경우에는 그 문제가 더 발생할 가능성이 커진다.
이게 NPE 발생하는지 확인하기 위해서는 SQL부터 확인해야 하고 JDBC API 코드의 데이터 변환 부분도 살펴봐야 한다.
하지만 JPA에서는 같은 방식으로 사용하더라도 category객체가 반드시 있음을 보장한다.
즉, 연관관계의 객체를 신뢰하고 마음껏 객체 그래프를 탐색하며 조회할 수 있다.
같은 값을 가지지만(동등성 o) 서로 다른 주소를 가진다(동일성 x)
assertFalse(menu1 == menu2);
assertEquals(menu1.getMenuName(), menu2.getMenuName());
System.out.println("menu1 = " + menu1);
System.out.println("menu2 = " + menu2);
하지만 JPA로 구현하는 경우 동일 비교가 가능해진다.
Menu menu1 = entityManager.find(Menu.class, 12);
Menu menu2 = entityManager.find(Menu.class, 12);
menu1 == menu2; //true