기본키 제약과 유니크 제약이 어떤 차이를 가지고 있는지 알아보고, JPA의 @Column(unique=true)과 @UniqueConstraint 을 살펴본다.
유니크 키는 테이블의 단일 또는 복수 컬럼으로서 레코드를 식별가능하게 한다. 기본키와 유니크 키는 모두 단일 컬럼 또는 컬럼 세트에 대한 유일성(uniqueness)을 보장한다.
유니크 제약은 컬럼 또는 컬럼 조합 안의 데이터가 각 행마다 모두 유일(unique)함을 보장한다. 기본 키는 묵시적 유니크 제약으로 기능한다.
JPA의 @Column(unique=true)과 @UniqueConstraint는 스키마 생성 프로세스와 제약 자동 생성으로 번역되는 어노테이션이다.
예시) Person 엔터티 생성
@Entity
@Table
public class Person implements Serializable {
@Id
@GeneratedValue
private Long id;
private String name;
private String password;
private String email;
private Long personNumber;
private Boolean isActive;
private String securityNumber;
private String departmentCode;
@JoinColumn(name = "addressId", referencedColumnName = "id")
private Address address;
//getters and setters
}
address 필드는 Adress 엔터티를 참조하는 필드이다.
@Entity
@Table
public class Address implements Serializable {
@Id
@GeneratedValue
private Long id;
private String streetAddress;
//getters and setters
}
@JoinColumn 어노테이션을 통해 어떤 컬럼을 외래키로 사용할 것인지 지정하는 것입니다. 위의 코드에서는 address 필드가 Address 엔터티의 id 프로퍼티를 참조하는 외래키로 사용되도록 설정되어 있습니다.
Person 엔터티에 id 기본키 외에도 중복 값이 없는 PersonNumber를 가지고 있다고 가정하자. 유니크 제약을 사용하여 이 필드에 중복값이 들어오지 못하게 설정한다.
Column 어노테이션 타입은 persistent 프로퍼티 또는 필드를 데이터베이스 열에 맵핑하는데, 아래와 같이 정의된다.
@Target(value={METHOD,FIELD})
@Retention(value=RUNTIME)
public @interface Column {
boolean unique;
//other elements
}
unique 속성이 컬럼이 유니크 키인지 특정해준다.
예시) 단일 필드에 대한 유니크 제약 정의
@Column(unique=true)
private Long personNumber;
@interface : Java 언어에서 사용되는 특별한 키워드로, 어노테이션을 정의할 때 사용됩니다. 어노테이션은 프로그램 코드에 메타데이터를 추가하는 방법 중 하나입니다. 즉, 클래스, 메소드, 필드 등의 요소에 추가 정보를 부여하거나 표시할 때 사용됩니다.
@Target(value={METHOD,FIELD}): 어노테이션을 적용할 수 있는 대상(타겟)을 나타냅니다. 해당 어노테이션은 메소드와 필드에 적용할 수 있습니다.
@Retention(value=RUNTIME): 이 어노테이션은 어노테이션 정보를 언제까지 유지할 것인지를 나타냅니다. RUNTIME으로 설정되어 있으므로 런타임 시에도 어노테이션 정보가 유지됩니다.
스키마 생성 프로세스를 실행하면 로그에서 검증할 수 있다.
[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UK_d44q5lfa9xx370jv2k7tsgsqt unique (personNumber)
UK_d44q5lfa9xx370jv2k7tsgsqt와 같은 제약조건 이름은 데이터베이스 시스템에서 자동으로 생성된 것입니다. 이 이름은 데이터베이스 시스템이 유니크 제약조건을 생성할 때 사용되는 내부적인 식별자이며, 보통은 시스템에 의해 자동으로 생성되는 경우가 많습니다.
Hibernate와 같은 ORM 도구가 데이터베이스 스키마를 관리할 때, 테이블의 제약조건 이름을 자동으로 생성하거나 지정할 수 있습니다. 이러한 이름은 데이터베이스 시스템의 특정 규칙을 따르거나, 랜덤한 문자열과 숫자의 조합을 사용하여 생성될 수 있습니다.
복합적인 유니크 키를 정의하기 위해 테이블에 제약을 추가한다. JPA에서는 @UniqueConstraint 어노테이션을 제공한다.
UniqueConstraint의 어노테이션 타입은 DDL 생성 시 유니크 제약이 포함되도록 특정한다.
@Target(value={})
@Retention(value=RUNTIME)
public @interface UniqueConstraint {
String name() default "";
String[] columnNames();
}
String과 String[] 자료형의 name, columnNames은 제약조건을 지정하는 요소이다.
Person 엔터티에서 personNumber와 isActive를 조합하여 중복되지 않는 복수의 컬럼 제약 조건을 만든다. @Table 어노테이션 아래 uniqueConstraints 속성으로 @UniqueConstraint 어노테이션을 대입한다.
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "personNumber", "isActive" }) })
각 어노테이션은 미리 정의된 속성들을 가지고 있고, 이러한 속성들을 사용하여 어노테이션의 동작을 설정하거나 제어할 수 있습니다.
@Table: 이 어노테이션은 클래스가 데이터베이스 테이블과 매핑되는 것을 나타냅니다.
uniqueConstraints: 이 속성은 해당 테이블에 유니크 제약조건(Unique Constraint)을 설정하는 역할을 합니다. 유니크 제약조건은 특정 열의 값들이 유일해야 함을 의미합니다.
@UniqueConstraint: 이 어노테이션은 유니크 제약조건을 정의하는 역할을 합니다. 여기서는 columnNames 속성을 사용하여 유니크 제약조건이 적용될 열의 이름을 지정합니다. 즉, "personNumber"와 "isActive" 두 열의 조합이 유일해야 합니다.
스키마 생성
[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UK5e0bv5arhh7jjhsls27bmqp4a unique (personNumber, isActive)
제약 조건에 이름을 지정할 수도 있다.
@Table(uniqueConstraints = { @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = { "personNumber", "isActive" }) })
스키마 생성
[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)
예시) 단일 엔터티에 다수의 유니크 제약조건을 부여
@Table(uniqueConstraints = {
@UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = {"personNumber", "isActive"}),
@UniqueConstraint(name = "UniqueSecurityAndDepartment", columnNames = {"securityNumber", "departmentCode"})})
스키마 생성 결과
[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)
[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UniqueSecurityAndDepartment unique (securityNumber, departmentCode)
Person 엔터티에는 Address 엔터티를 참조하는 address 필드가 있다. 이 필드에 유니크 제약을 부여하자
@Column(unique = true)
private Address address;
[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UK_7xo3hsusabfaw1373oox9uqoe unique (address)
컬럼 조합에 유니크 제약 부여하기. personNumber와 address에 유니크 제약을 부여한 후 uniqueConstraint 배열에 추가한다.
@Entity
@Table(uniqueConstraints =
{ //other constraints
@UniqueConstraint(name = "UniqueNumberAndAddress", columnNames = { "personNumber", "address" })})
[main] DEBUG org.hibernate.SQL -
alter table Person add constraint UniqueNumberAndAddress unique (personNumber, address)