

// JpaTest.java
@Configuration
public class JpaTest {
private EntityManager em;
private EntityTransaction tx;
@Bean
public CommandLineRunner testJpaBasicRunner(EntityManagerFactory emFactory) {
this.em = emFactory.createEntityManager();
this.tx = em.getTransaction();
return args -> {
ex1();
ex2_1stcache();
ex3_select();
ex4_equals();
ex5_delaycommit();
ex6_dirtychecking();
emFactory.close();
};
}
}
// MyMember.java
@Entity
@NoArgsConstructor
@Getter
@Setter
public class MyMember {
@Id
private Long id;
private String name;
}
EntityManagerFactory을 주입 받아 EntityManager와 EntityTransaction을 사용하기 위해 em,tx에 할당하였다. private void ex1() {
tx.begin();
MyMember myMember = new MyMember();
myMember.setId(1L);
myMember.setName("HelloA");
em.persist(myMember);
tx.commit();
em.close();
}
em.persist(myMember);가 호출되면 엔티티 메니저가 , 엔티티 객체는 영속성 컨텍스트의 1차 캐시에 영속화 되며 JPA의 관리하에 들어오게 된다.myMember엔티티 데이터를 저장하기 위한 쿼리문이 저장되게 된다.tx.commit(); 동시에 내부적으로는 em.flush()가 실행되며, DB로 쿼리문이 날아가 엔티티는 DB에 저장되고 트랜젝션은 끝나게 된다.em.close();를 통해 엔티티 매니저를 종료된다.ex2_1stcache(),ex3_select() private void ex2_1stcache() {
tx.begin();
/* 비영속 상태 */
MyMember myMember = new MyMember();
myMember.setId(1L);
myMember.setName("helloJPA");
/* 영속 1차 캐시*/
System.out.println("Berore==============");
em.persist(myMember);
System.out.println("After===============");
/* 쿼리문이 날아가지 않음 - 영속성 컨텍스트의 1차캐시에서 데이터를 가져오기 때문 */
MyMember findMyMember = em.find(MyMember.class, 1L);
System.out.println("findMember.getId() = " + findMyMember.getId());
System.out.println("findMember.getName() = " + findMyMember.getName());
tx.commit();
/* 영속 상태로 만들고 컨텍스트를 비운다 */
em.clear();
}
private void ex3_select() {
tx.begin();
/* 영속성 컨텍스트에는 현재 존재하고 있는 1차 캐시 데이터가 없기때문에 셀렉 쿼리를 날려서 데이터를 가져오게된다*/
MyMember reFindMyMember = em.find(MyMember.class, 1L);
System.out.println("reFindMember.getId() = " + reFindMyMember.getId());
System.out.println("reFindMember.getName() = " + reFindMyMember.getName());
em.close();
}
ex2_1stcache()에서 새로운 엔티티 객체를 생성하여 em.persist(myMember);로 영속화 하게 되면, 1차 캐시에 데이터가 저장되게 되며, MyMember findMyMember = em.find(MyMember.class, 1L);em.find()를 호출한 시점에 쿼리문이 날아가지 않은 것을 확인 할수 있다.persist()후 엔티티 메니저가 종료되거나 비워지지 않았다면 해당 데이터를 DB에 거치지 않고 조회 할수 있게 된다.em.clear();를 호출하여 엔티티 메니저를 비운 후 ex3_select()의 새로운 트랜잭션에서 em.find(MyMember.class, 1L);를 하게되면ex4_equals() private void ex4_equals() {
tx.begin();
/* 비영속 상태 */
MyMember myMember = new MyMember();
myMember.setId(1L);
myMember.setName("helloJPA");
em.persist(myMember);
tx.commit();
em.clear();
tx.begin();
MyMember findMyMember1 = em.find(MyMember.class, 1L);
MyMember findMyMember2 = em.find(MyMember.class, 1L);
System.out.println("findMember1 equals findMember2 = "+ findMyMember1.equals(findMyMember2));
em.close();
}
em.persist(myMember);, tx.commit();, em.clear(); 차례로 호출하여 DB에 데이터를 저장하고 엔티티 매니저를 비웠다.em.find(MyMember.class, 1L);로 같은 영속 엔티티를 두번 호출하여 두개의 변수에 할당해준다.equals()로 두개의 객체가 같은지 확인 해보면, true를 반환한다.ex5_delaycommit() private void ex5_delaycommit() {
tx.begin();
MyMember myMember1 = new MyMember();
myMember1.setId(1L);
myMember1.setName("helloJPA");
MyMember myMember2 = new MyMember();
myMember2.setId(2L);
myMember2.setName("helloSpring");
System.out.println("Persist Berore==============");
em.persist(myMember1);
em.persist(myMember2);
System.out.println("Persist After===============");
System.out.println("Commit==============");
tx.commit();
em.close();
}
System.out.println("Commit==============");이 실행 된 이후에 쿼리문이 날아가는 것을 확인 할 수 있다.commit()이 호출되는 시점에 쿼리문이 날아가도록 쓰기지연 기능을 지원하는 것을 확인 할 수 있다.ex6_dirtychecking() private void ex6_dirtychecking() {
tx.begin();
MyMember myMember1 = new MyMember();
myMember1.setId(1L);
myMember1.setName("helloJPA");
em.persist(myMember1);
tx.commit();
em.clear();
tx.begin();
MyMember findMyMember1 = em.find(MyMember.class, 1L);
System.out.println("findMember1.getName() = " + findMyMember1.getName());
findMyMember1.setName("helloSpring");
tx.commit();
em.clear();
tx.begin();
MyMember findMyMember2 = em.find(MyMember.class, 1L);
System.out.println("findMember2.getName() = " + findMyMember2.getName());
em.close();
}
persist()를 호출하여 영속성 컨텍스트에 등록 후 commit()으로 DB에 저장하고 엔티티 매니저를 초기화 했다.persist()를 호출 하지 않고 commit()만 호출한 다음, 엔티티 매니저를 초기화 했다."helloSpring"인 것을 확인 할수 있다.persist()를 호출하지 않더라도 commit()이 호출되는 시점에 엔티티의 변경된 데이터를 감지하여 업데이트 쿼리문을 자동을 날려 주는 것을 확인할 수 있다.clear() : 영속성 컨텍스트 초기화.close() : 영속성 컨텍스트 종료.merge() : 준영속(영속 상태였다가 영속성 컨텍스트에서 제거된 엔티티) 상태의 엔티티를 영속상태로 만들어 준다.detach(entity) : 해당 엔티티를 준영속 상태로 만든다.flush() : 영속상태의 데이터를 DB에 저장한다.Reference
https://www.baeldung.com/jpa-hibernate-persistence-context
https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html