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

우진님의 프로필 이미지
우진

작성한 질문수

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

기본 키 매핑

강사님 코드 그대로 했는데 결과가 다릅니다. @SequenceGenerator 값이 50씩 늘어나요.

작성

·

315

0

[질문 내용]
안녕하세요 김영한 강사님. 강의 잘 듣고 있습니다.

실습도중 저는 강사님과 똑같은 코드임에도 불구하고 다르게 동작하게 되어 질문 남기게 되었습니다.

GeneratedValue 전략에서

IDENTITY 전략은 persist 하는 과정에서 바로 DB insert를 하는 것을 이해했고

SEQUENCE 전략은 allocationSize를 통해 처음 call next value 2번 호출 후 -1 의 값이 나와야하는데 저는 -1이 되지 않습니다.

create 으로 하고 실행하고 create-drop 하고 실행하고 아예 캐시 문제인가 하여, DB를 전부 드랍후 다시 해보았는데도

TEAM_ID ID NAME

null 1 m4

null 2 null

null 3 null

null 4 null

null 52 m4

null 53 null

null 54 null

null 55 null

값이 이런식으로 저장됩니다. 강사님과 코드는 동일한데 무엇 때문에 이렇게 동작할까요?

package hellojpa;

import jakarta.persistence.*;

/**
 * @author : ewjin
 * @fileName : Member
 * @since : 24. 6. 20.
 */
@Entity
@SequenceGenerator(name = "MEMBER_SEQ_GENERATOR", sequenceName = "MEMBER_SEQ", initialValue = 1, allocationSize = 50)
public class Member {

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
	private Long id;

	@Column(length = 300)
	private String name;


	@ManyToOne
	@JoinColumn(name = "TEAM_ID")
	private Team team;

	public Long getId() {
		Class<? extends Member> a = getClass();
		System.out.println(a);
		return id;
	}

	public Team getTeam() {
		return team;
	}

	public void setTeam(Team team) {
		this.team = team;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

package hellojpa;

import jakarta.persistence.*;
import org.hibernate.Transaction;

import java.util.Arrays;
import java.util.List;

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 m1 = new Member();
			m1.setName("m1");
			Member m2 = new Member();
			m1.setName("m2");
			Member m3 = new Member();
			m1.setName("m3");
			Member m4 = new Member();
			m1.setName("m4");

			em.persist(m1);
			em.persist(m2);
			em.persist(m3);
			em.persist(m4);

			System.out.println("m1.getId() = " + m1.getId());
			System.out.println("m2.getId() = " + m2.getId());
			System.out.println("m3.getId() = " + m3.getId());
			System.out.println("m4.getId() = " + m4.getId());


			tx.commit();
		} catch (Exception e) {
			System.out.println("에러남=========================");
			tx.rollback();
			System.out.println(e.getCause());
			System.out.println(e.getMessage());
			System.out.println(e.getStackTrace());
			e.printStackTrace();
		} finally {
			em.close();
			emf.close();
		}


	}
}

답변 2

0

우진님의 프로필 이미지
우진
질문자

혹여나 설정 파일 문제인가 싶어 같이 첨부합니다.


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="hello">
        <properties>
            <!-- 필수 속성 -->
            <property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="jakarta.persistence.jdbc.user" value="sa"/>
            <property name="jakarta.persistence.jdbc.password" value=""/>
            <property name="jakarta.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<!--            <property name="hibernate.dialect" value="org.hibernate.dialect.MariaDBDialect"/>-->

            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments"  value="true"/>
            <property name="hibernate.jdbc.batch_size" value="10"/>
            <property name="hibernate.hbm2ddl.auto" value="update" />
<!--                        <property name="hibernate.hbm2ddl.auto" value="create" />-->
<!--            <property name="hibernate.hbm2ddl.auto" value="validate" />-->
<!--            <property name="hibernate.hbm2ddl.auto" value="create-drop" />-->
        </properties>
    </persistence-unit>

</persistence>

0

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

우진님의 질문을 세심하게 검했을 때, 질문하신 내용은 JPA의 @SequenceGenerator를 사용하여 엔티티의 ID 값을 자동으로 생성할 때 발생하는 문제와 관련이 있는 것으로 보입니다. 특히, allocationSize와 관련하여 예상치 못한 동작이 발생하는 상황에 대해 질문하신 것 같습니다.

해당 문제에 대해 비슷한 상황을 설명하고 해결책을 제안하는 내용이 있어서, 그 내용을 공유드립니다. 질문하신 내용에 대해 h2 버그인가요?에서 설명하고 있습니다.

이 질문에서도 JPA와 하이버네이트가 사용하는 시퀀스 생성 전략과 관련된 문제를 다루고 있습니다. 특히, 특정 전략(ex: @SequenceGenerator)을 사용할 때 어떻게 allocationSize가 작동하는지, 그리고 @GeneratedValue의 전략을 설정할 때 발생할 수 있는 일련의 행위들에 대해 설명합니다.

@GeneratedValue 전략이 SEQUENCE일 경우, 엔티티를 persist할 때마다 시퀀스 값을 가져오는 것이 아니라, allocationSize에 따라 일정 범위의 ID 값을 미리 할당하여 성능을 최적화할 수 있다는 점에서 중요합니다. 그러나 실제 어플리케이션과 데이터베이스의 상호작용이나, JPA 구현체와 데이터베이스 간의 동작 방식에 따라 예상과 다른 결과가 나타날 때가 있습니다.

특히 해당 답변에서는 다음과 같은 중요한 내용을 담고 있습니다:
- H2 데이터베이스를 사용할 때 allocationSize와 관련된 전략이 실제 어플리케이션 재시작 시 어떻게 동작하는지에 대한 예.
- 테스트 시나리오에 따라 allocationSize의 적용 방식이 어떻게 달라지는지의 설명.
- 결과에 영향을 미치는 하이버네이트와 데이터베이스의 동작 방식에 대한 이해.

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

우진님의 프로필 이미지
우진

작성한 질문수

질문하기