필드와 컬럼 매핑
객체의 필드와 데이터베이스의 컬럼을 매핑하는 방법에 대해 알아보겠다.
1. @Column
객체필드를 테이블 컬럼에 매핑한다
주요 속성들
- name = String
-> 테이블 컬럼에 매핑될때의 이름을 정의한다.
- nullable = boolean
-> null값 허용 여부를 선택한다
- unique = boolean
-> 한 컬럼에 유니크 제약조건을 걸때 사용한다.
- length = int
-> String값에만 사용하며, 최대 길이를 설정한다.
예시
@Entity
@Table(name = "USER")
public class User extends CommonDate{
@Id
@GeneratedValue
@Column(name = "ID")
private Long id;
@Column(name = "USER_NAME", nullable = false, unique = true)
private String userName;
@Column(name = "CONTRIBUTION_COUNT", nullable = false)
private long contributionCount;
@Column(name = "RANK", nullable = false)
private long rank;
public User(){}
}
2. @Enumerated
자바의 enum타입을 객체에 저장한다.
속성
- EnumType.STRING : enum 이름을 저장
- EnumType.ORDINAL : enum 순서를 저장
예시
@Enumerated(EnumType.STRING)
private TestEnum testEnum;
3. @Temporal (Column을 사용한다)
자바의 java.util.Date나 java.util.Calendar을 저장할때 사용한다.
하지만, 자바의 java.util.Date api는 문제점이 많아서 사용을 지양해야하는데, 자세한 이유는 아래 링크를 보자.
https://d2.naver.com/helloworld/645609
따라서, 최근엔, java.time의 LocalDate와 LocalDateTime을 주로 사용하며, 컬럼 매핑또한 @Column으로 하는걸 지향하는 편이다.
@Column으로 필드를 매핑 해도 DB에는 date타입으로 저장된다.,
예시)
@MappedSuperclass
public class CommonDate{
@Column(name = "LAST_MODIFIED_DATE")
private LocalDate lastModifiedDate;
public LocalDate getLastModifiedDate(){
return this.lastModifiedDate;
}
public void setLastModifiedDate(LocalDate lastModifiedDate){
this.lastModifiedDate = lastModifiedDate;
}
}
4. @Lob
데이터베이스 BLOB, CLOB타입과 매핑한다. CLOB과 BLOB은 각각은 매우 긴 문자열이나, 이미지, mp3등등 구조화되지않은 매우 큰 데이터를 저장한다.
(Lob에 저장할 수 있는 데이터 최대치는 컴퓨터 용량의 크기라고 한다.)
@Lob
private String lobString;
@Lob
private byte[] lobByte;
5. @Transient
@Transient어노테이션이 있는 필드는 매핑하지 않는다.
@Transient
private String transientString;
6. @Access
JPA가 Entity클래스 필드에 접근하는 방식을 지정한다.
속성
- AccessType.FIELD : 필드에 직접 접근한다. 필드 선언이 private이여도 접근 가능하다.
- AccessType.PROPERTY : getter와 setter를 이용해 접근한다.
@Access를 설정하지 않으면, @Id의 위치를 기준으로 접근 방식이 결정된다.
예시)
@Entity
@Table(name = "ACCESS_CLASS")
@Access(AccessType.PROPERTY)
public class AccessClass{
/.../
@Id
public String getId(){
return this.id;
}
@Column
public String getDate(){
return this.date;
}
}
7. 임베디드 타입
@Entity
public class TestEntity{
...
@Embedded
@AttributeOverrides({
@AttributeOverride(name="string", column=@Column(name = "IM_STRING")),
@AttributeOverride(name="integer", column=@Column(name="IM_INTEGER"))
})
private TestEmb testEmb;
...
}
@Embeddable
public class TestEmb{
...
private String string;
private Integer integer;
@Column(name = "IM_LOB")
@Lob
private String lob;
...
}
임베디드 타입은 외부 클래스를 '값 타입'(int, string...)로써 활용하게 해준다.
위 코드를 보자.
값 타입으로 '사용될' 클래스에 @Embeddable 어노테이션을 작성하고, 값 타입을 '사용할' 클래스안의 필드 메소드에 @Embedded를 작성하면된다.
값 타입의 안에는 @Column, @Lob등과 같이 컬럼 매핑을 직접 정의할수있으며, 필요시 @AttributeOverride로 속성을 재 정의 할수있다.
자세한 내용은 위의 코드를 참조하자.
이 임베디드 타입은 '값타입'의 범주 안에 포함된다. 다시말해, 값 타입인 Integer, String등의 특징을 그대로 가져와야하는데, 특징으로는 아래와 같다.
1. 서로 다른 주솟값, 같은 값을 갖고있는 값 타입은 비교시 동일해야한다. 즉, 값 타입은 동등성(equals) 비교로 비교해야한다.
2. 값 타입은 불변객체 이여야한다. 따라서, setter메소드를 만들지 않는다. 이는, 객체의 공유와 관련이 있는데, 만일 값 타입을 서로 다른 엔티티가 공유해서 사용한다면, 하나의 엔티티의 값 타입이 수정되었을때, 예상치못한 결과가 발생할수 있다.
값 타입을 불변으로 만들라는것은 안전을 위한 하나의 제약사항이다. 따라서, 불변으로 만들고 싶지 않다면, 엔티티끼리 공유하지않도록 복사해서 사용해야한다.
값 타입을 컬렉션에 보관하는 방법
@Entity
public class TestEntity{
...
@Id
@GeneratedValue
@Column(name = "TEST_ENTITY_ID")
private Long id
@ElementCollection
@CollectionTable(
name = "TESTEMB", joinColumns = @JoinColumn(name="TEST_ENTITY_ID")
)
private List<TestEmb> testEmbs;
...
}
@Embeddable
public class TestEmb{
...
private String string;
private Integer integer;
@Column(name = "IM_LOB")
@Lob
private String lob;
...
}
값 타입을 컬렉션에 보관하기 위해선, @ElementCollection과 @CollectionTable을 사용한다.
@CollectionTable의 name속성에는 값타입에 해당하는 엔티티 이름을 작성하고, joinColumns에는 값 타입과 매핑할 엔티티의 ID명을 작성한다.
또한, 값 컬렉션은 "다"를 보관하므로 느린 로딩 Lazy를 기본값으로 갖고있다.
'JPA' 카테고리의 다른 글
[JPA] 고급 매핑 - 상속 관계, 복합키와 식별 관계 (0) | 2021.10.17 |
---|---|
[JPA] 연관관계 매핑 (0) | 2021.10.14 |
[JPA] JPA 영속성 컨텍스트 (0) | 2021.10.11 |
[JPA] JPA 성능최적화 - N+1문제 (0) | 2021.10.04 |
[JPA] JPA란? - 패러다임의 불일치 (0) | 2021.09.25 |