인프런 커뮤니티 질문&답변

감바스님의 프로필 이미지
감바스

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

기본 키 매핑

Thread.sleep() 으로 identity 전략의 insert 쿼리 전송 시점을 테스트 해봤는데 궁금한 점이 있습니다.

해결된 질문

작성

·

105

·

수정됨

0

public class JpaMain {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {

            Member member = new Member();
            member.setUsername("A");

            System.out.println("======================");
            em.persist(member);
            Thread.sleep(9000);
            System.out.println("=======================");

            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }

        emf.close();
    }
}
@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String username;

    public Member() {
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

 

우선 생각 했던 결과는 현재 identity 전략이므로 em.persist() 할 경우 insert 쿼리가 DB에 바로 보내지고 DB의 Member 테이블에 값이 저장되는거를 예상했습니다.

실제 실행해 보면

======================

Hibernate:

/* insert for

jpa_basic.ex1_hello_jpa.hellojpa.Member */insert

into

Member (name, id)

values

(?, default)

 

Thread.sleep(9000) 전까지는 insert 쿼리가 콘솔에 잘 찍힙니다. 그래서 H2 콘솔에 데이터가 잘 저장이 됐는지 확인 해봤습니다.

image.png

결과는 저장이 되지 않았습니다.

Thread.sleep(9000)가 끝나고 나서야 데이터가 저장이 됩니다. 그래서 생각했던 결과인 identity 전략에서 em.persist() 할 경우 왜 DB에 바로 저장이 안되는건지 궁금합니다.

참고로 http://hibernate.hbm2ddl.auto 옵션은 create입니다.

 

감사합니다.

답변 1

0

안녕하세요, 인프런 AI 인턴입니다.

감바스님의 상황은 JPA에서 Identity 전략을 사용하여 엔티티를 DB에 insert할 때 발생하는 특정 동작에 대한 궁금증인 것 같습니다. Identity 전략은 엔티티를 영속 상태로 만들 때 (em.persist()) 즉시 DB에 insert 쿼리를 보내기 때문에, 실제 데이터베이스에 해당 엔티티의 정보가 저장되는 시점이 궁금하신 것으로 이해됩니다.

이와 관련하여, Identity 전략을 사용할 때 em.persist() 호출 시 즉각적으로 DB에 insert 쿼리가 날라가는 원리와, 트랜잭션 커밋(tx.commit()) 시점에 데이터베이스에 최종적으로 저장되는 과정을 알아보면 궁금증이 해소될 것 같습니다.

JPA를 사용할 때, Identity 전략으로 ID를 생성하는 경우 다음과 같은 특징을 가집니다:

  1. 즉시 insert 쿼리 실행: em.persist() 메소드를 호출할 때, JPA는 엔티티의 ID가 데이터베이스로부터 생성되어야 하며, 이를 위해 즉시 insert 쿼리를 실행합니다. 이는 엔티티의 식별자가 DB에 의해서 결정되므로, 해당 엔티티를 트랜잭션 안에서 사용하기 위해 필요한 절차입니다.

  2. 트랜잭션 커밋 시 데이터베이스에 반영: 실질적으로 데이터베이스에 저장되는 시점은 트랜잭션이 성공적으로 커밋되었을 때입니다. 즉, tx.commit()이 호출될 때 DB 트랜잭션이 완료되며, 이전에 insert된 엔티티가 실제로 저장됩니다.

감바스님의 경우, Thread.sleep(9000) 호출과 관계없이 em.persist() 시 데이터베이스에 즉시 insert 쿼리는 날라가지만, 트랜잭션이 커밋되기 전까지는 이러한 쿼리의 실행 결과(데이터 저장) 가 최종 확정되지 않습니다. 따라서 Thread.sleep() 동안에는 데이터베이스에 엔티티 정보가 보이지 않을 수 있습니다. 데이터베이스에 최종 반영은 tx.commit() 호출과 함께 이루어집니다.

관련하여, Identity 전략과 트랜잭션 커밋에 대한 좀 더 자세한 설명이 필요하면, IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행 하고 DB에서 식별자를 조회라는 질문과 답변을 참고하시는 것도 도움이 될 수 있습니다. 이 자료에서는 JPA의 Identity 전략 사용 시, em.persist() 호출 시와 tx.commit() 호출 시의 데이터 저장과 관련된 내용을 설명하고 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

감바스님의 프로필 이미지
감바스

작성한 질문수

질문하기