Java Persistence API
Object-relational mapping
JPA는 애플리케이션과 JDBC 사이에서 동작한다.
JPA는 패러다임 불일치를 해결
1차 캐시, 동일성 보장, 트랜잭션을 지원하는 쓰기 지연, 변경 감지, 지연 로딩
id값을 기준으로 엔티티에 1차 캐시 안에 저장해둠 -> DB보다 우선순위로 접근, 없을 경우 DB에서 조회 후 1차 캐시에 저장 및 반환 -> 한 트랜잭션 안에서만 도는 경우가 대다수이기에 성능에서 얻는 이점은 딱히 없음
// 비영속 상태
Member member = new Member();
member.setId(101L);
member.setName("HelloJPA");
// 영속 상태로 전환
System.out.println("=== before ===");
em.persist(member);
System.out.println("=== after ===");
Member findMember = em.find(Member.class, 101L);
System.out.println("findMember = " + findMember.getId());
System.out.println("findMember.getName() = " + findMember.getName());
em.persist를 통해 영속성 컨텍스트에 member를 저장해놨기 때문에 Select 쿼리가 나가지 않음
Member findMember1 = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);
tx.commit();
해당 코드도 마찬가지로 이미 101번 member를 영속성 컨텍스트에서 관리하고 있기에 쿼리가 2번 나가지 않음.
Member findMember1 = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);
System.out.println("result = " + (findMember1 == findMember2));
tx.commit();
두 엔티티의 동일성은 true 이다.
영속성 컨텍스트에는 안에 1차 캐시 뿐만 아니라 쓰기 지연 SQL 저장소가 있음, persist가 되면 해당 저장소에 SQL을 생성해둠.
transaction.commit()을 하는 순간에 flush를 해서 DB에 쿼리를 날림
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member1 = new Member(150L,"A");
Member member2 = new Member(160L,"B");
// 영속성 컨텍스트에 저장 및 쿼리 생성
em.persist(member1);
em.persist(member2);
// 이때 쿼리가 나감
tx.commit();
Member member = em.find(Member.class, 150L);
member.setName("ZZZZZ");
commit을 하면 엔티티와 스냅샷을 비교, 값을 최초로 영속성 컨텍스트에 들어온 상태를 스냅샷에 저장되어있는데 Entity가 변경이 되면 스냅샷과 비교하여 변경을 감지해 쓰기 지연 SQL 저장소에 Update SQL을 생성하고 DB에 쿼리를 날림
영속성 컨텍스트의 변경내용을 데이터베이스에 반영
Member member = new Member(200L, "member200");
em.persist(member);
em.flush();
tx.commit();
em.flush()를 통해 강제로 DB에 먼저 쿼리를 날리게함 -> 데이터베이스에 반영이 되는 과정
다만 commit()이나 JPQL의 경우 플러시가 자동으로 호출됨.
⚠️ 영속성 컨텍스트를 비우는 것이 아님
⚠️ 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
⚠️ 트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화 하면 됨
Member member = em.find(Member.class, 150L);
member.setName("AAAAA");
// 영속성 컨텍스트에서 제거
em.detach(member);
tx.commit();
해당 코드는 update 되지 않는다.
em.detach() / em.clear() / em.close()