persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence">
<persistence-unit name="hello">
<properties>
<!-- 필수 속성 -->
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<!-- 옵션 -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comment" value="false"/>
<property name="hibernate.id.new_generator_mappings" value="true" />
<property name="hibernate.jdbc.batch_size" value="10"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="connection.autocommit" value="false"/>
</properties>
</persistence-unit>
</persistence>
Member.java
import javax.persistence.*;
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "MEMBER_NAME", nullable = false)
private String name;
public Member() {}
public Long getId(){
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Member(Long id, String name){
this.id = id;
this.name = name;
}
}
JpaMain.java
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args ) {
System.out.println("시작 ------");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
//비영속 상태
Member member = new Member();
member.setId(1L); <------ 문제의 코드
member.setName("test");
System.out.println("=== 이전 =====");
//entity를 영속 (1차캐시에 저장한다)
em.persist(member);
System.out.println("=== 이후 =====");
tx.commit();
}catch(Exception e){
System.out.println("롤백이 진행됨");
System.out.println(e.getMessage());
e.printStackTrace();
tx.rollback();
}finally {
em.close();
}
}
}
@GeneratedValue(strategy = GenerationType.IDENTITY) 전략에 대해 검색해봄
기본키 생성을 데이터베이스에 위임한다.
id 값을 null로 하면 DB가 알아서 AUTO_INCREMENT 해준다
https://gmlwjd9405.github.io/2019/08/12/primary-key-mapping.html
[JPA] 기본키(PK) 매핑 방법 및 생성 전략 - Heee's Development Blog
Step by step goes a long way.
gmlwjd9405.github.io
위 글을 보니 문제가 어디인지 감이 잡힘.
데이터베이스에 id값을 생성하라고 위임을 해놓고 임의로 셋팅하려고 하니 문제가 발생된것으로 보임.
member.setId(1L); <------ 문제의 코드
[에러코드]
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: Member
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:762)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:742)
at JpaMain.main(JpaMain.java:22)
member.setId(1L); 이부분을 주석처리하면 아래와 같이 정상 동작함.
=== 이전 =====
Hibernate:
insert
into
Member
(MEMBER_ID, MEMBER_NAME)
values
(default, ?)
=== 이후 =====
====================