JPA 필드와 컬럼 매핑
JPA 필드와 컬럼 매핑
1. @Column
@Column은 객체 필드를 테이블 컬럼에 매핑하는 방법입니다.
가장 많이 사용되고 기능도 많지만, 속성중에 name과 nullable이 주로 사용되고, 나머지는 잘 사용하질 않습니다.
속성 | 기능 | 기본값 |
---|---|---|
name | 필드와 매핑할 테이블의 컬럼이름 | 객체의 필드 이름 |
insertable (거의사용X) |
엔티티 저장 시 이 필드도 같이 저장합니다. false로 설정하면 이 필드는 데이터베이스에 저장하지 않습니다. false 옵션은 읽기 전용일 때 사용합니다. |
true |
updateable (거의사용X) |
엔티티 수정 시 이필드도 같이 수정합니다. false로 설정하면 데이터베이스에 수정하지 않습니다. false 옵션은 읽기 전용일 때 사용합니다. |
true |
table (거의사용X) |
하나의 엔티티를 두 개 이상의 테이블에 매핑할 때 사용합니다. 지정한 필드를 다른 테이블에 매핑할 수 있습니다. |
현재 클래스가 매핑된 테이블 |
nullable(DDL) | null 값의 허용 여부를 설정합니다. false로 설정하면 not null 제약이 붙습니다. | true |
unique(DDL) | @Table의 uniqueConstraints와 같지만 한 컬럼에만 간단히 유니크 제약조건을 걸 때 사용합니다. 만약 두개 이상의 유니크 제약조건을 걸고 싶으면 @Table의 uniqueConstraints를 사용해야합니다. |
|
columnDefinition(DDL) | 데이터베이스 컬럼 정보를 직접 줄 수 있습니다. | 필드의 자바 타입과 방언 정보를 사용해서 적절한 컬럼 타입을 생성합니다. |
lenghth(DDL) | 문자 길이 제약조건, String 타입에만 사용합니다. | 255 |
precision, scale(DDL) | BigDecimal 타입에서 사용합니다.(BigInteger도 사용가능) precision은 소수점을 포함한 전체 자릿수를, scale은 소수의 자릿수 입니다. 참고로 double,float타입에는 적용되지 않습니다. 아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용합니다. |
precision = 19, scale=2 |
1-1 @Column 생략을 하면 어떻게 될까?
int data1; //@Column생략, 기본타입
data1 integer not null // 생성된 DDL
Integer data2; // @Column생략, 객체타입
data2 integer // 생성된 DDL
@Column
int data3; //@Column사용, 기본타입
data3 integer// 생성된 DDL
data3의 경우 @Column 어노테이션을 사용했는데, nullable이 true로 설정되기 때문에 안전하지 않을 수 있습니다.
기본타입은 null이라는게 존재하지 않기 때문입니다.
2. @Enumerated
속성 | 기능 | 기본값 |
---|---|---|
value | - EnumType.ORDINAL : enum 순서를 데이터베이스에 저장 - EnumType.String : enum 이름을 데이터베이스에 저장 |
EnumType.ORDINAL |
2-1. enum 클래스 선언
enum RoleType {
ADMIN,USER
}
2-1-1. enum 매핑 (EnumType.STRING)
@Enumerated(EnumType.STRING)
private RoleType roleType;
member.setRoleType(RoleType.ADMIN): // DB에 ADMIN으로 저장
2-1-2. enum 매핑 (EnumType.ORDINAL)
@Enumerated(EnumType.ORDINAL) // 기본값
private RoleType roleType;
member.setRoleType(RoleType.ADMIN): // DB에 0으로 저장
2-2. EnumType.STRING
- 장점 : 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전합니다.
- 단점 : DB에 저장되는 데이터 크기가 ORDINAL에 비해서 큽니다.
2-3. EnumType.ORDINAL
- 장점 : DB에 저장되는 데이터 크기가 작습니다.
- 단점 : 이미 저장된 enum의 순서를 변경할 수 없습니다.
ADMIN(0) , USER(1) 에서 ADMIN(0) , NEW(1) USER(2) 로 변경되면 망하게된다..
3. @Temporal
날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용합니다.
속성 | 기능 | 기본값 |
---|---|---|
value | - TemporalType.DATE : 날짜, 데이터베이스 date 타입과 매핑(예 : 2019 - 09 -09) - TemporalType.TIME : 시간, 데이터베이스 time 타입과 매핑(예 : 11:11.11) - TemporalType.TIMESTAMP : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑( 예: 2019 - 09 - 09 10:10:10) |
TemporalType은 필수로 지정해야 합니다. |
@Temporal(TemporalType.DATE)
private Date date; // 날짜
@Temporal(TemporalType.TIME)
private Date time; // 날짜
@Temporal(TemporalType.TIMESTAMP)
private Date timestamp; // 날짜와 시간
요즘에는 java.util.Date와 java.util.Calendar를 잘 안쓰고 있습니다.
그 대신에 LocalDateTime을 주로 이용하고 있기 때문에 해당 어노테이션은 잘 이용되지 않을 거라 생각됩니다.
아직 java.util.Date를 사용하고 있으면, 사용하지마세요.
저는 @Temporal를 이용하지 않고.
private LocalDate localDate; // MySQL DATE 타입
private LocalDateTime localDateTime; // MySQL DATETIME 타입
이렇게 사용하고 있습니다.
4. @Lob
데이터베이스 BLOB, CLOB 타입과 매핑합니다.
@Lob은 지정할 수 있는 속성이 없습니다. 대신에 매핑하는 필드 타입이 문자면 CLOB으로 매핑하고 나머지는 BLOB로 매핑합니다.
- CLOB : String, char[], java.sql.CLOB
- BLOB : byte[], java.sql.BLOB
@Lob
private String lobString;
@Lob
private byte[] lobByte;
//오라클
lobString clob,
lobByte blob,
//MySQL
lobString longtext,
lobByte longblob
//PostgreSQL
lobString text,
lobByte oid
5. @Transient
이 필드는 엔티티에 매핑해도 데이터베이스에 저장되지 않습니다.
객체에 임시로 값을 보관하고 싶을 때 사용합니다.
@Transient
private Integer temp;
6. @Access
JPA가 엔티티 데이터에 접근하는 방식을 지정합니다.
- 필드 접근 : AccessType.FIELD로 지정합니다. 필드에 직접 접근하는 방법입니다. 필드가 private이어도 접근이 가능합니다.
- 프로퍼티 접근 : AccessType.PROPERTY로 지정합니다. Getter를 사용하는 방법입니다.
@Access를 설정하지 않으면 @Id의 위치를 기준으로 접근 방식이 설정됩니다.
@Id 어노테이션이 필드에 붙어있으면 AccessType.FIELD로 접근 방식이 설정 됩니다.
6-1. 프로퍼티 접근 코드
@Entity
@Access(AccessType.PROPERTY) // @Id 어노테이션때문에 생략 가능.
public class Member {
private String id;
private String data1;
@Id
public String getId() {
return id;
}
@Column
public String getData1() {
}
}
6-2. 필드, 프로퍼티 접근 함께 사용
@Entity
public class Member {
@Id
private String id;
@Transient
private String firstName;
@Transient
private String lastName;
@Access(AccessType.PROPERTY)
public String getFullName() {
return firstName + lastName;
}
}
@Id가 필드에 있으므로 기본적으로 필드 접근 방식을 이용하지만, getFullName()만 프로퍼티 방식을 사용합니다.
따라서 엔티티를 저장할 때 FULLNAME 컬럼에 firstName + lastName의 결과가 저장됩니다.