EntityManager
는 Entity
를 영속성 컨텍스트에 보관하고 관리한다.persist()
== 영속화를 시키겠다 == 영속성 컨텍스트에서 관리하겠다1차 캐시에서 엔티티는 key(식별자)-value(Entity)로 관리되기 때문에 반드시 식별자(ID, PK)가 있어야 한다.
transaction.commit()
)하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 DB에 반영한다(FLUSH
).FLUSH
는 영속성 컨텍스트의 변경 내용을 DB에 동기화 하는 것이다. 이 때 등록, 수정, 삭제된 Entity가 DB에 반영된다.비영속(new/transient)
영속성 컨텍스트에 전혀 관계가 없는 상태
영속(managed)
EntityManger
에 의해서 호출되는 함수
persist()
: 영속성 컨텍스트에서 관리되도록 한다. detach()
: 영속성 컨텍스트에서 더 이상 관리되지 않도록 한다.clear()
: 영속성 컨텍스트에서 관리되는 Entity들을 모두 지워버려 모든 준영속 상태로 만든다.close()
: 영속성 컨텍스트를 종료하여 모든 Entity들을 준영속 상태로 만든다.merge()
: 모든 Entity들이 준영속 상태에서 영속 상태로 만든다.remove()
: 영속성 컨텍스트에서 분리하고 DB에서도 삭제한다.JPA의 모든 변경은 트랜잭션 안에서 일어나야 한다.
Entity를 영속성 컨텍스트에서 관리하기 위해 항상 트랜잭션을 시작하고 끝내야한다.
transaction.begin()
em.persist(Entity)
INSERT INTO ~
) 저장Entity
를 key-value로 저장transaction.commit()
em.flush()
가 호출되어 쓰기 지연 저장소에 쿼리를 수행하여 DB와 Entity를 동기환한다.1차 캐시에 데이터가 남아 있다면 DB에 질의하지 않고 1차 캐시에 저장된 데이터를 가지고 온다.
tx.commit()은 FLUSH를 하는 것이기에 1차 캐시 이용이 가능하다.
1차 캐시에 관하여 참고
find()
변경 감지(Dirty Checking)
변경 감지는 영속 상태의 엔티티에만 적용된다.
trasaction.commit()
을 통해 em.flush()
발생참고)merge()
에 대하여
Spring Data JPA에서 save()
를 할 때 엔티티에 ID가 있으면 생성이 아니라 수정으로 보고 em.merge(entity)
를 수행하게 된다. 문제는 모든 속성이 변경되기 때문에 null값 업데이트의 가능성이 있다. 따라서 수정시에는 Dirty Checking이 권장된다.
merge()
실행em.remove(entity)
transaction.commit()
로 인해 em.flush
발생하고 DELETE ...
쿼리를 날린다.기본적으로 EntityManager를 생성할 때 영속성 컨텍스트가 하나 만들어진다. 하지만 Spring 같은 컨테이너 환경의 JPA에서는 여러 EntityManager가 하나의 영속성 컨텍스트를 공유한다.
스프링 컨테이너는 트랜잭션 범위의 영속성 컨텍스트 전략을 기본으로 사용한다. 이 전략은 트랜잭션이 시작할 때 영속성 컨텍스트를 생성하고 트랜잭션이 끝날 때 영속성 컨텍스트를 끝낸다.
트랜잭션 범위의 한 클래스에서 repo1 의 어떤 em.A() 수행하는 것과, repo2 의 em.B() 를 수행하는 것은 둘 다 똑같은 영속성 컨텍스트를 사용하는 것이다.
Transaction 범위의 A 클래스, Transaction 범위의 B 클래스가 한 repo의 em.A()를 동시에 사용해도 트랜잭션에 따라 접근하는 컨텍스트가 다르다.
@Service
public class MovieService {
@Autowired
private EntityManager entityManager;
...
}
스프링은 싱글톤 기반으로 동작 하기에 위와 같이 EntityManager를 주입 받았다면, 여러 스레드가 같은 EntityManager에 접근을 하여 스레드 세이프 하지 않다고 생각될 수 있으나 실제로는 컨테이너에서 EntityManager 대신 proxy를 주입한다. 그리고 이 proxy는 EntityManager를 생성하여 thread safe를 보장할 수 있다.
@Entity
객체가 영속성 컨텍스트에서 관리될 수 있음을 나타낸다.
@Table
@Table(name = "member")
name을 이용하여 table 이름을 설정
create
create-drop
update
validate
none
JPA auto configuration 사용시 AUTO DDL 옵션을 위 항목에 작성해야한다.
JPA auto configuration을 사용하지 않고 직접 Bean으로 설정하면서 JpaProperties를 사용하는 경우 AUTO DDL 옵션을 위 항목에 작성해야한다.
사실 이에 대한 내용을 어제 TIL에서 작성하였다...
구지 명시를 해야 할까?라는 생각이 들 수도 있지만 명시를 해 놓으면 RDB 테이블의 모습을 개발자가 쉽게 유추할 수 있기 때문에 명시를 권장한다!
NOT NULL option
unique 조건
varchar
insertable
RDB에 insert 안함
updatable
RDB에 update 안함
false 이면 컬럼에 조작을 가하지 않겠다.
자주 사용되지는 않는다.
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@GeneratedValue(strategy = GenerationType.IDENTITY)
@GeneratedValue(strategy = GenerationType.AUTO)
@GeneratedValue
@Column(name = "order_datetime", columnDefinition = "TIMESTAMP")
TIMESTAMP값이 저장되어 진다.
enum값 저장을 원하는 경우
객체 그래프 탐색이 불가능하다.