Spring Boot Entity 엔티티

김정훈·2024년 7월 24일

Spring

목록 보기
19/24

Entity 설계하기

1. 엔티티 매핑 관련 애노테이션

애노테이션설명
@Entity클래스를 엔티티로 선언
@Table엔티티와 매핑할 테이블을 지정
@Id테이블의 기본키에 사용할 속성을 지정
@GeneratedValue키 값을 생성하는 전략 명시
@LobBLOB, CLOB 타입 매핑
@CreationTimestampinsert 시 시간 자동 저장
@UpdateTimestampupdate 시 시간 자동 저장
@Enumeratedenum 타입 매핑
@Transient해당 필드 데이터베이스 매핑 무시
@Temporal날짜 타입 매핑
@CreatedDate엔티티가 생성되어 저장될 때 시간 자동 저장
@LastModifiedDate조회한 엔티티의 값을 변경할 때 시간 자동 저장

@Entity

엔티티명 : 기본값 : 클래스명
참고) JPQL(Java Persistence Query Language)
name, value - 엔티티 명을 직접 설정

@Table

name : 테이블 명
: 엔티티 명 == 테이블명

실제 테이블명 CH_MEMBER, 클래스는 Member로 정의하고 싶은 경우?

@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
@Table(name="CH_MEMBER")
public class Member {
    @Id
    private Long seq;
    private String email;
    private String password;
    private String userName;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;
}

인덱스 설정

@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
@Table(indexes ={
        @Index(name="idx_created_at_desc", columnList = "createdAt DESC"),
        @Index(name="up_email_password", columnList = "email, password", unique = true)
}) //인덱스설정
public class Member {
    @Id
    private Long seq;
    private String email;
    private String password;
    private String userName;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;
}


@Temporal

Date, Calendar 클래스 관련 : 날짜, 시간, 날짜 + 시간
java.time API 사용시 필요 X
LocalDate, LocalTime, LocalDateTime

@CreatedDate, @LastModifiedDate

엔티티 변화 감지를 통해서 변경(DB와 상관 X), 변화 감지를 위한 이벤트 리스너
@EntityListeners(AuditingEntityListener.class)을 통해 변화감지를 감독해야한다.

@MappedSuperclass
@Getter @Setter
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime modifiedAt;
}

@GeneratedValue

strategy: 키 생성 전략을 지정합니다. GenerationType 열거형(enum)을 사용하여 다음 중 하나를 선택

전략설명
AUTO기본값, 기본 생성 전략을 사용합니다. 데이터베이스에 따라 적절한 전략이 자동으로 선택됩니다.
IDENTITY데이터베이스의 IDENTITY 컬럼을 사용합니다. 주로 MySQL, PostgreSQL 사용. Oracle에서 사용 못함.
SEQUENCE데이터베이스 시퀀스를 사용합니다. 주로 Oracle, PostgreSQL에서 사용.
TABLE키 생성을 위해 별도의 테이블을 사용합니다. 모든 데이터베이스에서 사용할 수 있습니다.
@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
public class Member {
    @Id @GeneratedValue
    private Long seq; //시퀀스가 자동으로 생성.
    private String email;
    private String password;
    private String userName;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;
}
@SpringBootTest
@Transactional
public class Ex03 {

    @PersistenceContext
    private EntityManager em;

    @Test
    void test1() {
        Member member = new Member();
        member.setEmail("user01@test.org");
        member.setPassword("12345678");
        member.setUserName("사용자01");
        member.setCreatedAt(LocalDateTime.now());

        em.persist(member);

        Member member2 = new Member();
        member2.setEmail("user02@test.org");
        member2.setPassword("12345678");
        member2.setUserName("사용자02");
        member2.setCreatedAt(LocalDateTime.now());

        em.persist(member2);

        em.flush();

        em.clear();

        Member _member1 = em.find(Member.class, member.getSeq());
        System.out.println(_member1);

        Member _member2 = em.find(Member.class, member2.getSeq());
        System.out.println(_member2);

    }
}

@Lob

BLOB, CLOB 타입 매핑

@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
public class Member {
    @Id @GeneratedValue
    private Long seq;
    private String email;
    private String password;
    private String userName;
    @Lob
    private String introduction;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;
}

@CreationTimestamp, @UpdateTimestamp

@CreationTimestamp, @UpdateTimestamp : 표준이아니기 때문에 사용 지양

@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
public class Member {
    @Id @GeneratedValue
    private Long seq;
    private String email;
    private String password;
    private String userName;
    @Lob
    private String introduction;
    
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    private LocalDateTime modifiedAt;
}
@SpringBootTest
@Transactional
@TestPropertySource(properties = "spring.profiles.active=test")
public class Ex04 {

    @PersistenceContext
    private EntityManager em;

    @Test
    void test1() throws Exception {
        Member member = new Member();
        member.setEmail("user01@test.org");
        member.setPassword("12345678");
        member.setUserName("사용자01");

        em.persist(member);
        em.flush();
        em.clear();

        member = em.find(Member.class, member.getSeq());
        System.out.println(member);

        Thread.sleep(5000);
        member.setUserName("(수정)");
        em.flush();
        em.clear();

        member = em.find(Member.class, member.getSeq());
        System.out.println(member);
    }


}
Member(seq=1, email=user01@test.org, password=12345678, userName=(수정), introduction=null, createdAt=2024-07-23T15:44:40.011288, modifiedAt=2024-07-23T15:44:45.076144)

@Enumerated

기본값은 Enum의 Ordinary 숫자(순서 번호)으로 되어있기 때문에, 값이 변경될수도 있는 문제가 있다. 그렇기 때문에 String으로 사용

@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
public class Member {
    @Id @GeneratedValue
    private Long seq;
    private String email;
    private String password;
    private String userName;
    @Lob
    private String introduction;

    @Enumerated(EnumType.STRING) //String 으로 사용
    private Authority authority;

    @CreationTimestamp
    private LocalDateTime createdAt;

    @UpdateTimestamp
    private LocalDateTime modifiedAt;
}

@Transient

DB에 반영되지 않음.
엔티티에 URL주소, 파일주소 등의 값들이 필요한경우가 존재. 또한 이런 값들을 2차가공할 필요가있음. 이런경우 데이터베이스에 저장하는 것보다 @Transient사용해서 데이터베이스에 저장하지 않는 것이 좋음

@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
public class Member {
    @Id @GeneratedValue
    private Long seq;
    private String email;
    private String password;
    private String userName;
    //@Lob
    @Transient
    private String introduction;

    @Enumerated(EnumType.STRING)
    private Authority authority;

    @CreationTimestamp
    private LocalDateTime createdAt;

    @UpdateTimestamp
    private LocalDateTime modifiedAt;
}

2. @Column

테이블을 생성할 때 컬럼에는 다양한 조건들이 들어갑니다. 예를 들면 문자열을 저장하는 VARCHAR 타입은 길이를 설정할 수 있고, 테이블에 데이터를 넣을 때 데이터가 항상 존재해야 하는 Not Null 조건 등이 있습니다. @Column 어노테이션의 속성을 이용하면 테이블에 매핑되는 컬럼의 이름, 문자열의 최대 저장 길이 등 다양한 제약 조건들을 추가할 수 있습니다.

속성설명기본값
name필드와 매핑할 컬럼의 이름 설정객체의 필드 이름
unique(DDL)유니크 제약 조건 설정
insertableinsert 가능 여부true
updatableupdate 가능 여부true
lengthString 타입의 문자 길이 제약조건 설정255
@nullable(DDL)null 값의 허용 여부 설정, false로 설정하면 DDL 생성시에 not null 제약조건 추가
@columnDefinition데이터베이스 컬럼 정보 직접 기술
@Column(columnDefinition = "varchar(5) default '10' not null")
precision, scale(DDL)BigDecimal 타입에서 사용(BigInteger 가능) precision은 소수점을 포함한 전체 자리수이고,
scale은 소수점 자시수 Double과 float 타입에는 적용되지 않음.
@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
public class Member extends BaseEntity {
    @Id @GeneratedValue
    private Long seq;
    private String email;
    private String password;
    
    @Column(name ="name")
    private String userName;
    
    //@Lob
    @Transient
    private String introduction;

    @Enumerated(EnumType.STRING)
    private Authority authority;
}

unique, nullable

@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
public class Member extends BaseEntity {
    @Id @GeneratedValue
    private Long seq;
    @Column(nullable = false, unique = true)
    private String email;
    @Column(nullable = false)
    private String password;

    @Column(nullable = false, name ="name")
    private String userName;

    //@Lob
    @Transient
    private String introduction;

    @Enumerated(EnumType.STRING)
    private Authority authority;
}

length

@Data
@Entity //엔티티 에노테이션 설정하면 자동으로 테이블이 생성
public class Member extends BaseEntity {
    @Id @GeneratedValue
    private Long seq;
    @Column(length = 60, nullable = false, unique = true)
    private String email;
    @Column(length = 65, nullable = false)
    private String password;

    @Column(length = 40, nullable = false, name ="name")
    private String userName;

    //@Lob
    @Transient
    private String introduction;

    @Column(length = 10)
    @Enumerated(EnumType.STRING)
    private Authority authority;
}

insertable, updateable

@Getter @Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column(insertable = false)
    private LocalDateTime modifiedAt;
}

createdAt : 2024-07-24T10:26:33.324995, modifiedAt: null
createdAt : 2024-07-24T10:26:33.324995, modifiedAt: 2024-07-24T10:26:38.425257

columnDefinition

사용 지양

4. 복합키

1) @IdClass

@NoArgsConstructor : 기본생성자
@AllArgsConstructor : 모든 멤버 변수로 초기화 생성자
@EqualsAndHashCode : 클래스에 대해 equals()와 hashCode() 메서드를 자동으로 생성해줍니다. 이를 통해 수동으로 해당 메서드를 작성해야 하는 번거로움을 덜 수 있습니다.

기본키를 여러 컬럼을 조합해서 생성
ex) 게시글 조회수 - UV : 브라우저 정보(User-Agent) + IP + 회원번호(0) : UID + 게시글 번호(ID)

BoardView

@Data
@Entity
@IdClass(BoardViewId.class)
public class BoardView {
    @Id
    private long seq;

    @Id
    @Column(name="_uid")
    private int uid; //uid는 오라클의 예약어이기 때문에, @Column(name="_uid")로 변경해줘야한다.

}

BoardViewId

@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class BoardViewId {
    private long seq;
    private int uid;
}

2) @Embbedld @Embbdedalbe

@IdClass대신에 사용

@Data
@Entity
public class BoardView {
    @EmbeddedId
    private BoardViewId id;
}
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class BoardViewId {
    private long seq;
    @Column(name="_uid")
    private int uid;
}

5. Auditing을 이용한 엔티티 공통 속성화

1) @MappedSuperclass

공통 속성화를 위한 상위 클래스. 추상클래스를 상속을 통해 공통으로 사용될 속성들을 공유.
AuditorAware 인터페이스

2) @EntityListeners

엔티티의 라이프사이클 이벤트를 리스닝하기 위해 사용됩니다.

3) @EnableJpaAuditing

Spring Boot 애플리케이션에서 JPA 감사(Auditing) 기능을 활성화합니다. 주로 @CreatedDate@LastModifiedDate와 같은 필드를 자동으로 관리하기 위해 사용됩니다.

global.entities

@Getter @Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime modifiedAt;
}

member.entities

public class Member extends BaseEntity { //상속
    @Id @GeneratedValue
    private Long seq;
    private String email;
    private String password;
    private String userName;
    //@Lob
    @Transient
    private String introduction;

    @Enumerated(EnumType.STRING)
    private Authority authority;
}
profile
안녕하세요!

0개의 댓글