시작하기 앞서 저의 글에대한 피드백이나 지적은 언제나 환영입니다 😊
em.persist(member);
엔티티 매니저를 사용해 member(회원엔티티)를 영속성 컨텍스트에 저장한다는 의미이다.
: 객체를 생성한 상태, 아직 영속성 컨텍스트에 저장하지 않은 상태.
Member member = new Member();
: 객체를 저장한 상태, 영속성 컨텍스트에 의해 관리된다
em.persist(member);
: 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(member);
//특정 엔티티만 준영속 상태로 전환 -> 영속성 컨텍스트에서 분리하는 것
em.detach(member);
//영속성 컨텍스트를 완전히 초기화 -> 관리되던 엔티티는 준영속 상태가 됨
em.clear();
//영속성 컨텍스트를 종료 -> 관리되던 엔티티는 준영속 상태가 됨
em.close();
: 객체를 삭제한 상태
em.remove(member);
//1차 캐시에 저장됨
em.persist(member);
//1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
Member findMember2 = em.find(Member.class, "member2");
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b); //동일성 비교 true
변수들은 서로 다른 메모리에서 생성되기 때문에 동일성 비교를 했을 때 동일성이 보장되지 않지만
영속된 엔티티들은 영속성컨텍스트가 관리해주므로 1차캐시에 있는 같은 엔티티를 반환받았기 때문에 같은 인스턴스 이므로 동일성이 보장된다
동일성 비교 : 실제 인스턴스가 같다
==
을 사용해 비교한다.동등성 비교 : 실제 인스턴스는 다를 수 있지만 인스턴스가 가지고 있는 값이 같다.
->equals()
메소드를 사용하여 비교한다
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA); em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋
즉, 내부 SQL저장소에 쿼리문들을 모아뒀다가 트랜잭션이 커밋될때 모아둔 쿼리문을 DB에 보낸다.
: 이것을 트랜잭션을 지원하는 쓰기지연이라고 한다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
//em.update(member) 이런 코드가 있어야 하지 않을까?
transaction.commit(); // [트랜잭션] 커밋
:위 처럼 update같은 코드가 있어야 하지 않을까?
결과부터 말하자면 없어도 된다.
영속성 컨텍스트가 관리해주는 엔티티는
플러시 시점에 1차캐시(스냅샷)와 비교해 변경된 점이 있다면 자동으로 update쿼리문을 날려준다.
//삭제 대상 엔티티 조회
Member memberA = em.find(Member.class, “memberA");
em.remove(memberA); //엔티티 삭제, DB에서도 삭제됨
em.flush()
로 직접 호출하는 방법 em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//중간에 JPQL 실행
query = em.createQuery("select m from Member m", Member.class);
List<Member> members= query.getResultList();
: 플러시 모드 옵션을 보면 알 수 있다.
em.setFlushMode(FlushModeType.AUTO)
: 커밋이나 쿼리를 실행할 때 플러시 (defualt값)em.setFlushMode(FlushModeType.COMMIT)
: 커밋 할 때만 플러시JPA에서는 가장 중요한 부분이 2개 있다고 합니다.
바로 영속성관리와 연관관계매핑 입니다.
그 중 중요한 한가지 영속성관리에 대해 정리해봤습니다.
영속성 컨텍스트의 내부 동작 방식을 이해하며 굉장히 흥미로웠습니다.
그리고 이 내부동작방식을 이해하지 못하면 JPA를 활용한 개발은 암기가 될 것 같다고 생각이 들었습니다.
긴 글 읽어주셔서 감사합니다.😊