# Table of Contents

# Entity Mapping

Hibernate의 Entity Mapping에 대해 정리한다.

# @Entity

테이블과 매핑할 클래스에는 @Entity 어노테이션을 필수로 붙여아한다.

@Entity
public class MemberEntity {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String email;

    @Column
    private String password;
}

Hibernate는 리플렉션으로 엔티티 객체를 생성하기 때문에 @Entity 사용 시 기본 생성자를 반드시 정의해야한다.















 
 
 
 


@Entity
public class MemberEntity {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String email;

    @Column
    private String password;

    // 기본 생성자
    public void MemberEntity() {

    }
}

# @Table

엔티티와 매핑할 테이블을 지정한다. name 속성으로 생성될 테이블의 이름을 직접 지정할 수 있다.


 



















@Entity
@Table(name = "member")
public class MemberEntity {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String email;

    @Column
    private String password;

    // 기본 생성자
    public void MemberEntity() {

    }
}

@Table을 생략하면 클래스 이름으로 테이블이 생성된다.

@Entity
public class MemberEntity {
    // ...
}

# 기본키

# 단일 기본키와 @id

영속성 컨텍스트는 엔티티를 식별자 값으로 구분하므로 반드시 엔티티에 식별자 값이 있어야한다. @id를 사용하면 단일 컬럼의 기본키를 지정할 수 있다.





 





@Entity
@Table(name = "member")
public class MemberEntity {

    @Id
    private Long id;

    // 생략 ...
}

@GeneratedValuestrategy속성을 GenerationType.IDENTITY로 지정하면 기본키 생성을 데이터베이스에게 위임한다. MySQL의 경우 AUTO_INCREMENT를 추가하는 것과 동일하다.






 





@Entity
@Table(name = "member")
public class MemberEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 생략 ...
}
create table member (
    id bigint NOT NULL AUTO_INCREMENT PRIMARY KEY
);

# 복합 기본키

복합키를 생성하려면 먼저 Serializable인터페이스를 구현한 식별자 클래스를 정의해야한다. 또한 식별자 클래스는 equal()hashCode() 메소드를 구현해야한다.

public class OrderId implements Serializable {

    private Long memberId;
    private Long productId;

    @Override
    public boolean equals(Object o) { ... }

    @Override
    public int hashCode() { ... }

}

그 다음 @IdClass어노테이션으로 식별자 클래스를 지정하면 된다.



 











@Entity
@Table(name = "order")
@IdClass(OrderId.class)
public class Order {

    @Id
    @Column(name = "member_id")
    private Long memberId;

    @Id
    @Column(name = "product_id")
    private Long productId;
}

# @Column

@Column은 테이블의 컬럼을 엔티티 클래스의 멤버변수에 매핑하는데 사용된다.

# name 속성

생성되는 테이블 컬럼의 이름을 지정한다.










 


 





@Entity
@Table(name = "member")
public class MemberEntity {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "email")
    private String email;

    @Column(name = "password")
    private String password;

    // 생략 ...
}

name 속성을 생략하면 멤버변수의 이름으로 컬럼을 생성한다.

# nullable 속성

nullable = falseNOT NULL 제약조건을 추가할 수 있다.










 


 





@Entity
@Table(name = "member")
public class MemberEntity {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String email;

    @Column(nullable = false)
    private String password;

    // 생략 ...
}

실행되는 DDL은 다음과 같다.



 
 



create table member {
    id biging not null,
    email varchar(255) not null,
    password varchar(255) not null,
    primary key (id)
}

# length 속성

문자열의 크기를 지정할 수 있다.










 








@Entity
@Table(name = "member")
public class MemberEntity {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 100)
    private String email;

    @Column
    private String password;

    // 생략 ...
}


 




create table member {
    id biging not null,
    email varchar(100),
    password varchar(255),
    primary key (id)
}

# unique 속성

컬럼을 유일키로 지정할 수 있다.







 





@Entity
@Table(name = "member")
public class MemberEntity {
    
    // 생략 ..

    @Column(unique = true)
    private String email;

    // 생략 ...
}
create table member {
    email varchar(100) UNIQUE KEY,
    // ...
}

# columnDefinition 속성

생성할 컬럼 정보를 직접 지정할 수 있다.







 





@Entity
@Table(name = "member")
public class MemberEntity {
    
    // 생략 ..

    @Column(columnDefinition = "VARCHAR(100) DEFAULT 'empty'")
    private String name;

    // 생략 ...
}

# @Enumerated

열거형(enum)타입을 매핑할 때 사용한다. 다음과 같은 열거형이 있다고 가정하자.

enum GenderType {
    MAN, WOMAN, UNKNOWN
}

이 열거형은 두 가지 방법으로 테이블이 매핑할 수 있다.

# EnumType.ORDINAL

EnumType.ORDINAL은 열거형에 정의된 순서대로 MAN은 0, WOMAN은 1, UNKNOWN은 2로 매핑한다.





 





@Entity
@Table(name = "member")
public class MemberEntity {
    
    @Enumerated(EnumType.ORIGINAL)
    private GenderType gender;

    // 생략 ...
}
member.setGenderType(GenderType.MAN)

EnumType.ORDINAL는 다음과 같은 장단점이 있다.

  • 데이터베이스에 저장되는 크기가 작다.
  • 이미 저장된 열거형의 순서를 바꾸거나 추가할 수 없다.

# EnumType.STRING

EnumType.STRING은 열거형을 문자열로 저장한다. MAN은 문자열 MAN, WOMAN은 문자열 WOMAN, UNKNOWN은 문자열 UNKNOWN은로 저장되는 것이다.





 





@Entity
@Table(name = "member")
public class MemberEntity {
    
    @Enumerated(EnumType.STRING)
    private GenderType gender;

    // 생략 ...
}
member.setGenderType(GenderType.MAN)

EnumType.STRING는 다음과 같은 장단점이 있다.

  • 데이터베이스에 저장되는 크기가 크다.
  • 이미 저장된 열거형의 순서를 바꾸거나 추가할 수 있다.

열거형의 속성이 추가될 가능성이 있다면 EnumType.STRING를 사용하는 것이 안전하다.

# @Temporal

날짜 타입을 매핑하는데 사용한다.





 






@Entity
@Table(name = "member")
public class MemberEntity {
    
    @Temporal
    @Column(name = "created_at")
    private LocalDataTime createdAt;

    // 생략 ...
}

# @Transiet

해당 어노테이션이 붙은 멤버변수는 데이터베이스 컬럼으로 매핑하지 않는다.

@Entity
@Table(name = "member")
public class MemberEntity {
    
    @Transiet
    @Column
    private String temp;

    // 생략 ...
}

# 유일키

# 단일 유일키

@Columnunique 속성으로 단일 컬럼의 유일키를 생성할 수 있다.








 





public class MemberEntity {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String email;

    // 중략..
}

# 복합 유일키

@Table 어노테이션의 uniqueConstraints 속성으로 복합 컬럼의 유일키를 생성할 수 있다.




 
 
 
 




















@Entity
@Table(
    name = "member",
    uniqueConstraints = {@UniqueConstraint(
        name = "unq_email_name",
        columnNames = {"email", "name"}
    )}
)
public class MemberEntity {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String email;

    @Column
    private String name;

    @Column
    private String password;

    // 생략 ...
}

실행되는 DDL은 다음과 같다.

ALTER TABLE member
ADD CONSTRAINT unq_email_name UNIQUE (email, name);

# Entity Lifecycle Method

Hibernate는 엔티티가 영속, 준영속, 삭제될 때 특정 메소드가 콜백되도록 구현할 수 있다. 이를 Entity Lifecycle Method라고 하며, 7개의 어노테이션으로 정의한다.

어노테이션 설명
@PrePersist 엔티티가 영속화되기 전 호출된다.
@PostPersist 엔티티가 영속화된 후 호출된다.
@PreUpdate 엔티티가 변경되기 전 호출된다.
@PostUpdate 엔티티가 변경된 후 호출된다.
@PreRemove 엔티티가 삭제되기 전 호출된다.
@PostRemove 엔티티가 삭제된 후 호출된다.
@PostLoad 조회 연산으로 엔티티가 데이터베이스에서 영속성 컨텍스트로 로드될 때 호출된다.
import javax.persistence.*;
import java.util.*;

@Entity
@Table(name= "member")
public class MemberEntity {

    // ...

    @PostLoad
    public void onPostLoad() {

    }
    
    @PrePersist
    public void onPrePersist() {
        
    }
    
    @PostPersist
    public void onPostPersist() {
        
    }
    
    @PreUpdate
    public void onPreUpdate() {
        
    }
    
    @PostUpdate
    public void onPostUpdate() {
        
    }
    
    @PreRemove
    public void onPreRemove() {
        
    }
    
    @PostRemove
    public void onPostRemove() {
        
    }

    // ...
}