[Spring] Entity 매핑 관련 어노테이션 정리

WOOK JONG KIM·2022년 11월 18일
0

패캠_java&Spring

목록 보기
53/103
post-thumbnail

@Entity

JPA를 사용해 테이블과 매핑할 클래스에 붙여주는 어노테이션
-> 이를 붙임으로서 JPA에서 해당 클래스를 관리

속성

name : JPA에서 사용할 엔티티 이름을 지정, Default 값으론 클래스 이름을 엔티티 이름으로 지정

@Entity(name = "user2")
public class User {}

기본 생성자가 꼭 필요

final, enum, interface, innter class에서는 사용 불가

필드(변수)를 final로 선언 불가


@Table

엔티티와 매핑할 테이블을 지정

  • @Entity(name ="")의 경우 말그대로 엔티티의 이름을 정할때 사용-> 이는 HQL에서 엔티티를 식별할 이름을 정함
  • @Table(name ="")의 경우 Database에 생성될 table의 이름을 지정할때 사용
  • @Table이 없고 @Entity(name ="")만 존재하는 경우, @Entity의 name 속성에 의해, Entity와 Table 이름이 모두 결정됨

속성

name : 매핑할 테이블의 이름, 생략시 @Entity(name = " ")의 값을 사용

catalog : catalog 기능이 있는 DB에서 catalog 매핑

schema : schema 기능이 있는 DB에서 schema 매핑

uniqueConstraints : DDL 생성 시 유니크 제약조건 생성
-> 스키마 자동 생성 기능을 사용해 DDL을 만들때만 사용

indexes : 테이블 인덱스 지정

@Entity
@Table(name = "user3")
@Getter
@Setter
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
}


@Id

특정 속성을 기본키로 설정하는 어노테이션

JPA 엔티티 객체의 식별자로 사용할 필드에 적용하며, 유니크한 DB의 컬럼과 맵핑하는것이 보통

@Entity(name="user2")
@Table
@Getter
@Setter
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
}

@Id 어노테이션만 붙이면 기본키는 직접 부여해야함
-> 보통 DB 설계시에는 자동 부여 되게끔 함(@GeneratedValue)

생성 전략엔 크게 IDENTITY, SEQUENCE, TABLE이 있다

IDENTITY : 기본키 생성을 DB에 위임(Mysql)

SEQUENCE : DB 시퀀스를 사용해서 기본 키 할당(ORACLE)

TABLE : 키 생성 테이블 사용(모든 DB 사용 가능)

AUTO : 선택된 DB에 따라 자동으로 전략 선택


@Column

객체의 필드를 테이블 컬럼과 매칭

@Column
private String name;

속성

name : 필드와 매칭할 테이블의 칼럼의 이름을 지정, default는 필드 이름으로 대체

insertable : true -> 엔티티 저장 시 필드 값 저장, false -> 필드 값 저장 되지 않음

처음에 DDL 동작 시 사용된 쿼리를 보면 이해 쉬움

updatable : true -> 엔티티 수정 시 값이 수정, false -> 엔티티 수정 시 값이 수정되지 않음

ex) 생성 날짜 필드

table : 하나의 엔티티를 두개 이상의 테이블에 매핑할 때 사용

nullable : null값 허용 여부

unique : 컬럼에 유니크 제약 조건 부여

columnDefinition : 데이터 베이스 컬럼 정보를 직접 부여

length : 문자 길이 제약

precision,scale : BigDecimal 타입에서 자릿수 설정 시 주로 사용

insertable

//Entity
@Entity(name="user2")
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue
    private Long id;
    @Column(insertable = false)
    private String name;
    private String age;
}

//Service
@Service
@RequiredArgsConstructor
public class TestService {
    private final EntityManager em;
    @Transactional
    public void test() {
        User user = User.builder()
                .age("12")
                .name("test")
                .build();
        em.persist(user);
    }
}

이때 네임 컬럼에 test를 입력하였더라도 DB에는 값이 들어가지 않음

updatable

@Entity(name="user2")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Setter
public class User {
    @Id
    @GeneratedValue
    private Long id;
    @Column(updatable = false)
    private String name;
    private String age;
}

//Service
@Service
@RequiredArgsConstructor
public class TestService {
    private final EntityManager em;
    @Transactional
    public void test() {
        User user = User.builder()
                .age("12")
                .name("test")
                .build();
        em.persist(user);
        user.setName("change test");
    }
}

이때도 마찬가지로 change test로 변경값이 지정되지 않음

columnDefinition

@Entity(name="user2")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Setter
public class User {
    @Id
    @GeneratedValue
    private Long id;
    @Column(unique = true)
    private String name;
    @Column(columnDefinition = "VARCHAR(15) NOT NULL")
    private String age;
}

@Access

JPA가 엔티티 데이터에 접근하는 방식 지정

속성

AccessType.FIELD : 필드에 직접 접근, private이여도 가능
AccessType.PROPERTY : getter를 통해 접근

@Access 어노테이션 지정 안할 시 @Id의 위치를 기준으로 접근

@Entity(name = "user2")
@Table(name = "user3")
@Getter
@Setter
@Access(AccessType.FIELD)
public class User {
    @Id
    @GeneratedValue
    private Long id;
}

기본적으로 위 코드에 @Access(AccessType.FIELD)가 있을 때와 없을 때의 동작 방식이 같음
-> @Id 어노테이션 설정 시 기본적으로 적용

프로퍼티 접근 사용 예시

@Entity(name = "user2")
@Table(name = "user3")
@Setter
@Access(AccessType.PROPERTY)
public class User {

    @GeneratedValue
    private Long id;

    @Id
    public Long getId() {
        return id;
    }
}

프로퍼티 접근 + 필드 접근 혼용 예시

@Entity(name = "user2")
@Table(name = "user3")
@Getter
@Setter
public class User {
    @Id
    @GeneratedValue
    private Long id;

    @Transient
    private String name;

    @Access(AccessType.PROPERTY)
    public String getFullName() {
        return name + " hello";
    }
    protected void setFullName(String firstName) { }
}

//Service
@Service
@RequiredArgsConstructor
public class TestService {
    private final EntityManager em;
    @Transactional
    public void test() {
        User user = new User();
        user.setName("aaa");
        em.persist(user);
    }
}

위 경우 칼럼명이 aaa hello로 지정됨


@Enumerated

자바 enum 타입을 매핑할 때 사용

속성

value :

EnumType.ORDINAL : enum 순서를 DB에 저장
EnumType.STRING : enum 이름을 db에 저장

예시

//Enum 클래스
public enum RoleType {
    ADMIN, USER
}

//Entity
@Entity(name = "user2")
@Table(name = "user3")
@Getter
@Setter
public class User {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @Enumerated(value = EnumType.ORDINAL)
    private RoleType ordinal;
    @Enumerated(value = EnumType.STRING)
    private RoleType string;
}

//Service
@Service
@RequiredArgsConstructor
public class TestService {
    private final EntityManager em;
    @Transactional
    public void test() {
        User user = new User();
        user.setName("test");
        user.setOrdinal(RoleType.ADMIN);
        user.setString(RoleType.ADMIN);
        em.persist(user);
    }
}

String ADMIN으로 지정된 반면 ordinal은 ADMIN의 순서인 0이 지정되었음

만약 enum의 ADMIN앞에 값이 추가된다면 ADMIN은 순서 상 1번이 되므로 조회가 안됨
-> 되도록이면 STRING을 사용하자


@Temporal

날짜 타입을 매핑할때 주로 사용

속성

value :

TemporalType.DATE : 날짜, DB date 타입과 매핑(ex:2020-02-12)

TemporalType.TIME : 시간, Db time 타입과 매핑(ex: 12:12:12)

TemporalType.TIMESTAMP : 날짜와 시간 DB timestamp 타입과 매핑(2020-02-12 12:12:12)


@Lob

Db BLOB, CLOB 타입과 매핑하기 위해 사용

정의할 속성은 따로 없지만 필드 타입이 문자열이면 CLOB, 나머지는 BLOB를 매핑
-> String, int가 있다면 각각 LONGTEXT, LONGBLOB로 매핑됨


@Transient

이 어노테이션 붙인 필드는 DB에 저장 및 조회하지 않음

entity는 데이터의 대한 객체이기에 DB RECORD 그대로 반영하지만 객체로서 역할도 하기에 DB RECORD와는 별개로 필드를 가지고 싶어하는 니즈도 있음
-> 붙이면 영속성 처리에서 제외가 됨

붙인 칼럼은 DB칼럼에 추가되지 않는것 확인 가능

profile
Journey for Backend Developer

0개의 댓글