엔티티 식별자
JPA는 엔티티를 관리하는 영속성 컨텍스트라는 공간이 있고 persist()를 통해 이곳에 저장된 엔티티 객체들은 JPA의 관리 대상이 됩니다. JPA의 관리 대상이 되었다는것은 엔티티의 상태가 변경되면 DB에 해당 엔티티에 대한 데이터가 JPA가 생성한 쿼리에 의해 UPDATE 되어진다는 뜻이며, EntityManager를 통해 삭제, 삽입, SELECTE 되어진다는 뜻입니다.
그런데 JPA는 영속성 컨텍스트에서 관리되는 엔티티 객체들을 구분할 필요가 있는데, 이때 필요한 것이 식별자 입니다. 식별자로 지정되는 속성은 @Id 애노테이션이 맵핑되어 있어야 합니다. 또한 속성에 맵핑되는 DB 테이블의 컬럼은 UNIQUE한 컬럼이어야 합니다. 즉 데이터가 중복되거나 NULL이 허용되는 컬럼이어서는 안됩니다.
식별자 직접 할당하여 관리하기
JPA에서는 엔티티의 식별자를 생성 및 할당하는 몇 가지 방법이 있는데, 그 중 한가지는 어플리케이션에서 직접 엔티티를 생성할때 할당하는 것입니다. 직접 식별자를 할당하는것은 식별자 생성을 DB에게 맡기지 않고 직접 생성해야 하는 특별한 규칙이 필요할 때 사용합니다. 예를 들어 사용자를 식별하는데에, 주민등록 번호와 같이 단순 시퀀스한 숫자가 아니라 특별한 규칙이 필요한 경우가 있습니다.
@Entity
@Table(name = "user_info")
public class User {
@Id
private String number; |
cs |
엔티티 객체를 생성하고 EntityManager를 통해 영속성 컨텍스트에 persist() 하기 전에 식별자를 할당해주면 됩니다.
transaction.begin();
User user = new User("910527-1234567", "도로락", "서울특별시"); //식별자를 직접 할당
entityManager.persist(user); //영속성 컨텍스트에 persist()
transaction.commit(); |
cs |
식별자를 중복 할당하여 저장하는 경우
만약 식별자가 중복되는 일이 발생 한다면 JPA 구현체에 따라 다르지만 하이버네이트의 경우 다음과 같이 ConstraintViolationException이 발생합니다. 이후 Caused by 메시지에 jdbc 레벨의 Duplicate entry ~~ 라는 메시지가 출력됩니다.
org.hibernate.exception.ConstraintViolationException: could not execute statement
...생략...
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '910527-1234567' for key 'number' |
cs |
식별자로 사용 가능한 필드 타입
식별자로 사용 가능한 필드 타입은 다음과 같은 것들이 있습니다.
-
int, long, float, double 같은 기본 자료형(Primitive Type)
-
Integer, Long 같은 자바 래퍼 클래스 타입(Wrapper Class)
-
String 문자열
-
java.util.Date, java.sql.Date
-
java.math.BigDecimal, java.math.BigInteger
식별자를 할당하지 않고 저장하는 경우
만약 식별자를 수동으로 할당하는 전략을 사용할때 식별자를 할당하지 않고 엔티티 객체를 저장하려 하면 IdentifierGenerationException을 감싼 PersistenceException 예외가 발생하게 됩니다. IdentifierGenerationException는 하이버네이트의 예외인데, JPA는 식별자를 할당하지 않았을때에 어떤 예외가 던져져야 하는지를 정의하고 있지 않기때문에 구현체별로 던져지는 예외가 상이합니다.
다음은 하이버네이트를 사용했을 때 식별자를 할당하지 않고 저장하려 한 경우에 발생하는 예외 출력 내용입니다.
javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned beforeQuery calling save():
...생략...
Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned beforeQuery calling save(): |
cs |
'JPA - Hibernate' 카테고리의 다른 글
[JPA] xxx.Hobbies is not mapped as an embeddable 오류 발생 원인 및 해결 방법 (0) | 2019.03.12 |
---|---|
[JPA] 식별자 할당 SEQUENCE(시퀀스) 사용 전략 (2) | 2018.07.28 |
[JPA - Hibernate] Dialect(방언)이란? 하이버네이트 Dialect 종류 (0) | 2018.07.22 |
[JPA] 엔티티 식별자 DB에서 할당받기. @GeneratedValue와 GenerationType.IDENTITY 전략. (0) | 2018.07.21 |
[JPA] @Id 애노테이션 필드 또는 메서드에 적용시 동작 차이점 (4) | 2018.07.05 |