SQL 중심 개발의 문제점? (SQL Mapper)
- 자바(객체지향)과 RDB(관계형데이터베이스)의 패러다임 불일치
=> 객체지향 개념(상속,다형성,참조 등)이 DB스키마와 일대일대응이 불가능
=> 테이블에 컬럼이 추가된 경우, 컬럼명이 변경된 경우 해당 테이블과 관련있는 모든 쿼리 수정 필요
- 처음 실행한 SQL에 따라 객체가 가진 데이터 범위가 결정됨
public class Mebmer {
String name;
Team team;
}
위 객체의 인스턴스를 조회할 때
select * from MEMBER WHERE name = "sth";
으로 조회한다면 (team = null)인 상태가 됨
=> 모든 데이터를 로딩할 수 없기 때문에 상황에 맞는 쿼리를 여러개 생성하고 관리해야함
결론적으로 SQL Mapper를 사용하면 DB 스키마에 종속된 개발을 할 수 밖에 없음
(객체지향으로 개발할수록 Mapping에 드는 추가적인 노력이 필요함)
DB와 자바(서비스로직)을 분리 => JPA
JPA: 객체가 가진 데이터를 자바 컬렉션 다루듯 DB에 저장할 수 있도록 하는 인터페이스
- JPA는 DB와 자바 객체사이에서 객체-관계 간 맵핑(ORM)을 해줌
- DB 접근을 위한 JDBC API를 추상화해줌(벤더 독립성 확보)
- 서비스는 객체지향으로, 디비는 관계형디비로 독립적인 설계 가능
- 객체와 테이블의 맵핑 관계를 JPA가 이해할 수 있는 형식으로 정의한 것이 "Entity"
- 일반적으로 두 매체 사이에 인터페이스를 두면 그로 인해 성능 최적화할 수 있는 가능성이 있음
1) 데이터를 모아뒀다가 한번에 전송(buffer writing)
2) 데이터 캐싱
- JPA에 의해 생성된 Entity는 동일한 트랜잭션 내에서 같은 key 값으로 조회된 경우 같은 객체(같은 객체참조)임을 보장함(영속성 컨텍스트에 의해서)
영속성 컨텍스트
: JPA가 관리하는 내부 영역
- em.persist(obj);를 수행하면 obj는 영속성 컨텍스트에 포함됨
- "1차캐시"라는 영역이 존재하는데 트랜잭션의 라이프사이클을 공유하며, entity의 변경,조회된 결과는 이 영역에 보관됨
- 실제로 조회된 entity의 멤버변수를 변경하면 이후 commit할 때 자동으로 udpate 쿼리가 생성되어 적용되는데, 이는 1차캐시에 (key,entity,스냅샷(영속성컨텍스트에 처음 생성되었을때의 entity)) 형태로 저장되어 commit 되기 전 현재 entity와 스냅샷을 비교해 update,delete 쿼리를 생성해주기 때문 => "dirty checking"
영속성 컨텍스트와 Entity의 존재로 인해 어플리케이션 입장에서는 DB에 종속성을 줄이고 객체지향관점에서 개발할 수 있음