자바 진영의 ORM 기술 표준이다. 이를 구현한 ORM 프레임 워크는 Hibernate, EclipseLink, DataNucleus가 있는데 학습에서는 Hibernate를 이용하겠다.
SQL중심의 개발에서 객체중심의 개발을 할 수 있게 해주는 기술이다.
ORM?
Object-Relational Mapping으로 객체와 관계형 데이터베이스를 매핑한다는 뜻이다.
EntityManagerFactory
데이터베이스를 하나만 사용하는 애플리케이션은 일반적으로 엔티티 매니저 팩토리를 하나만 생성한다. 이러한 팩토리 생성비용은 굉장히 크다.
모든 스레드가 공유해서 사용한다.
EntityMavager
엔티티 매니저는 팩토리를 통해 생성이 가능하며 여러 스레드가 동시에 접근하면 동시성 문제가 발생한다. 따라서 스레드간 공유는 절대 안된다.
엔티티 매니저는 DB 연결이 정확히 필요한 시점에 커넥션을 획득한다.
엔티티를 영구 저장하는 환경이라는 뜻으로 엔티티 매니저를 통해 엔티티를 저장, 조회시 엔티티 매니저는 영속성 컨텍스트에 해당 엔티티를 보관하고 관리한다.
영속성 컨텍스트 장점
1차캐시 지원한다.엔티티 조회시 1차 캐시를 지원해주어 성능향상에 효과가 있다. 이러한 장점은 동일성 또한 보장해주는데 User테이블이 있을 경우 user1조회시 캐시에서 조회해 오기 때문에 같은 객체를 참조하게 되어 DB에서 직접 조회시 동일성이 보장되지 않는 점과 차이가 있다.
쓰기지연을 지원한다. 엔티티를 저장시 영속성 컨텍스트에 저장되면 1차캐시에 엔티티가 등록됨과 동시에 쿼리가 저장되는데 이러한 쿼리를 바로 DB로 전달되는게 아니라 트랜잭션이 끝날때 마지막에 한번에 저장된 쿼리를 전달한다. 이러한 기능을 flush라고 하며 이 또한 성능 향상에 도움이 된다.
변경감지를 지원한다. 영속성 컨텍스트는 엔티티가 관리되면 처음 상태값을 스냅샷이라는 형태로 초기값을 기억하고 있는다. 그러다 플러시가 일어날 경우 영속상태인 엔티티에 대해 현재 상태값을 스냅샷과 비교하여 달라졌을 경우 변경쿼리를 작성하여 쿼리 저장소에 추가 저장한다.
플러시는 영속성 컨텍스트의 변경 내용을 DB에 반영하는 것을 말하며 쓰기 지연 SQL 저장소의 저장된 쿼리들을 DB에 전송한다.
여기서 중요한 것은 플러시가 일어났다고해서 영속성 컨텍스트가 초기화 된다고 생각하면 안된다. DB와 동기화를 할 뿐 초기화는 이루어지지 않는다.
영속성 컨텍스트를 플러시하는 방법
엔티티매니저를 통해 직접호출 (em.flush())
트랜잭션 커밋 시 플러시가 자동 호출
트랜잭션 커밋시에 변경된 내용을 반영해야하므로 플러시를 자동하도록 지원한다.
JPQL 쿼리 실행 시 플러시 자동 호출
JPQL을 이용해 조회시 같은 트랜잭션안에 있는 내용중 반영안되어 있는 내용들에 대해서 조회가 안되는 문제를 해경하기 위해 JPQL을 사용시 플러시를 자동하도록 지원한다.
주의사항
기본 생성자는 필수
final 클래스, enum, interface, inner 클래스는 사용불가
저장할 필드에 final 사용불가
@Entity
해당 클래스를 테이블과 매핑되는 객체임을 나타내는 어노테이션
@Table
매핑할 테이블 정보를 알려주며 생략할 경우 엔티티의 이름과 테이블 맵핑
@DynamicUpdate
업데이트 쿼리 생성시 기본전략은 모든 컬럼이 작성되는데 변경된 필드(컬럼)만 반영하는 방법으로 상황마다 다르지만 컬럼이 30개 이상되지 않는다면 기본전략과 비교해 성능차이는 거의 없다고 한다.
@Id
테이블의 기본 키에 매핑하는 어노테이션으로 필드에 적용한다.
@GeneratedValue
테이블 기본키 할당 방식을 지정하는 어노테이션이다.
@Colum
테이블 컬럼에 해당 필드가 맵핑되는 정보를 나타내는 어노테이션이다. 자바 기본 자료형 사용시 null값을 할당할 수 없는데 해당 필드가 기본형이면 옵션으로 nullable = false로 지정해야 예외가 발생하지 않는다.
@Enumerated
enum타입을 매핑할 때 사용한다.속성으로 value를 줄 수 있는데 EnumType.ORDINAL 또는 EnumType.STRING이 있고 오리지널은 이넘에 저장된 순서 스트링은 문자그대로 저장한다. 오리지널은 이넘에 순서가 바뀌면 문제가 되므로 왠만하면 스트링으로 사용 주의!기본값 오리지널
@Temporal
날짜 타입을 매핑할 때 사용한다.
@Lob
길이 제한이 없는 CLOB, BLOB타입을 매핑할 때 사용한다.
@Transient
특정 필드를 DB에 매핑하지 않는다.