비영속 (new/transient)
-> 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
영속 (managed)
-> 영속성 컨텍스트에 관리되는 상태
준영속 (detached)
-> 영속성 컨텍스트에 저장되었다가 분리된 상태
삭제 (removed)
-> 삭제된 상태
1차 캐시
동일성(identity) 보장
트랜잭션을 지원하는 쓰기 지연 (Transactional write-behind)
변경 감지 (Drity Checking)
지연 로딩 (Lazy Loading)
//엔티티를 생성한 상태 (비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
//엔티티를 영속
//em = entity manager
em.persist(member);
    fun practice1(){
        //JPA 특성을 가지고 있다.
        val emf = Persistence.createEntityManagerFactory("hello")
        val em = emf.createEntityManager()
        // 비영속 상태이다.
        val member = Member()
        member.id = 101L
        member.title = "테스트맨"
        // transaction
        val transaction = em.transaction
        transaction.begin()
        println("BEFORE") // before 찍힘
        // 영속화 한다 (persist)
        // 저장할 때 사용한다.
        em.persist(member) // insert 날라감
        println("AFTER") // after 찍힘
        transaction.commit()
        em.close()
        emf.close()
    }
이 function을 실행시키면 BEFORE, AFTER이 차례로 print가된 뒤 persist된다.
왜?
println("BEFORE") -> 1차 캐시로 저장 -> println("AFTER") -> commit(DB로 전달)
되기 때문
여기서 중요한 것은 1차 캐시 이다.
JPA를 통해 DB에 보내기 전 메모리에 1차 캐시로 데이터를 저장하고,
그 상태에서 @Transaction 안에서 즉시 사용될 수 있다.
    fun practice2(){
        // EntityManager 생성
        val emf = Persistence.createEntityManagerFactory("hello")
        val em = emf.createEntityManager()
        //객체를 생성한 상태(비영속)
        val member = Member()
        member.id = 101L
        member.title = "회원"
        val transaction = em.transaction
        transaction.begin()
        //1차 캐시에 저장됨
        em.persist(member)
        //3번 멤버 조회
        val member1 = em.find(Member().javaClass, 101L)
        println("조회 결과 : " + member1.title)
        transaction.commit()
        em.close()
        emf.close()
    }
practice2 function를 실행하면, DB에서 불러오는 것이 아니라
1차캐시 에서 불러올 수 있다는 것을 알 수 있다.
즉, JPA는 1차 캐시에서 먼저 데이터를 찾고 없으면 DB에서 조회한다.
    fun practice3(){
        // EntityManager 생성
        val emf = Persistence.createEntityManagerFactory("hello")
        val em = emf.createEntityManager()
        val transaction = em.transaction
        transaction.begin()
        //100번 멤버 조회
        val member1 = em.find(Member().javaClass, 100L)
        //100번 멤버 조회
        val member2 = em.find(Member().javaClass, 100L)
        println("비교 결과 : " + (member1 === member2))
        transaction.commit()
        em.close()
        emf.close()
    }
이건 어떻게 처리될까?
member1과 member2를 따로 조회하는 것이 아니라,
한 번에 조회한 뒤 비교 결과를 출력한다.