-자바 ORM표준 JPA프로그래밍 을 읽고 정리한 내용입니다.
객체지향 프로그래밍은 추상화,상속,캡슐화 등의 장치로 복잡성을 제어할 수 있게 도와준다. 떄문에 자바의 객체는 필드,메소드 외에도 상속을 받았다거나 다른 객체를 참조하는 일이 있다. 이러한 객체는 관계형데이터베이스와 괴리가 있다. 관계형 데이터베이스에는 상속,참조,다형성 같은 개념이 없으므로 이런 개념을 데이터베이스에서 실현시키기 위한 방법이 필요하다.
슈퍼타입,서브타입 관계를 이용한다. 부모객체의 테이블에서 DTYPE컬럼을 이용해 어떤 자식테이블과 관계가 있는지 정의한다. 그리고 저장할 떄에는 객체를 분해해서 각각의 테이블에 INSERT한다. 상속받은 객체의 테이블에 1번, 본인의 객체 테이블에 1번으로 2번에 걸쳐 INSERT된다.
조회를 할 떄에도 부모테이블,자식테이블을 조인한 다음 그 결과에서 SELECT해야 상속객체를 조회할 수 있다. 이런 과정을 JPA 메소드에서 해주기에 편리하다.
객체는 getTeam()과 같은 메소드로 참조한 객체를 불러오지만,테이블에서 외래키를 이용한다.
member.getId() 을 MEMBER 테이블의 PK에 저장
member.getTeam.getId() 을 MEMBER테이블 FK에 저장
member.getUsername() 을 MEMBER테이블 컬럼으로 저장
위와 같은 과정을 거쳐야 저장된다.
조회는 JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID 과 같은 과정으로
TEAM_ID가 같은 테이블을 조인한 결과에서 SELECT해야 참조객체까지 조회할 수 있다. JPA는 이 과정또한 메소드를 통해 지원한다.
sql을 직접 다루면 처음 실행하는 sql에 따라 어디까지 탐색할 수 있는지 정해진다 이 말을 처음 봤을 떄 무슨 말인가 했다. 생각을 해보니 처음 sql문을 실행하면서 join을 한 테이블 까지만 탐색을 할 수 있다는 말이다.
SELCT M.*,T*
FROM MEMBER M
JOIN TEAM ON M.TEAM_ID=T.TEAM_ID
위와 같은 SQL문을 처음 실행한후 이 결과에서 탐색을 하려한다면 getTeam()의 결과만을 알 수 있다. 실제 객체는 Order객체 또한 참조하고있더라도 sql문에서 join ORDER 까지 해둔게 아닌 이상 Order객체는 조회할 수 없다. 하지만 앞으로 어떤 객체를 탐색할지 모두 미리 알 수는 없는 노릇이다. 그렇다고 모든 참조 테이블을 미리 join해 놓은것도 큰 낭비가 된다. 그렇기에 조회범위에 따라 sql문을 선언한 범위가 다른 DAO를 다 만들어 놓았어야 했다는 슬픈이야기이다. jpa에서는 sql의 범위 결정을getOrder과 같은 조회를 실행할 할떄까지 지연했다가 조회를 행할 떄 JOIN을 함으로써 이 문제를 해결한다.
DAO에서 sql을 통해 구현을 할 경우 같은 ID로 조회를 하더라도 DAO에 접근한 떄가 다르다면 다른 인스턴스에서 값을 반환하기 떄문에 동일성비교(==) 가 되지 않았다. JPA에서는 같은 트랜잭션 안에서는 동일한 인자로 조회하면 같은 결과가 리턴되는 것을 보장한다.