JPA에서 **엔티티(Entity)**는 관계형 데이터베이스의 테이블과 대응하며, JPA가 관리하는 클래스를 말합니다.
이는 Java 클래스로 선언하며, 보통 domain 패키지에 포함되고, 아래와 같이 구성됩니다
@Entity
@Table
public class Member{
...
}
JPA에서 테이블과 매핑할 클래스는 @Entity 애너테이션을 필수로 붙여야 합니다. @Entity 적용 시에는, 클래스가 아래 주의사항을 따라야 합니다
JPA는 자바 리플렉션(Java Reflection API)을 통해 엔티티 정보를 받는데, 이 때 생성자 인자 정보를 가져올 수 없으므로 기본 생성자는 필수적으로 필요합니다. 몇몇 JPA구현체(하이버네이트같은)에서는 바이트코드 조작(Bytecode Manipulation)을 통해 이런 문제를 회피한다고 합니다.
자바는 클래스를 생성하면 기본 생성자를 자동으로 만들지만, 만약 생성자가 추가된다면 기본 생성자가 사라지므로 주의해야 합니다. (대부분의 IDE에서 잡아주긴 하지만..)
속성
@Table은 엔티티와 매핑할 데이터베이스 테이블을 지정합니다. 생략 시, 엔티티 이름을 테이블 이름으로 사용합니다.
catalog 기능: 데이터베이스의 인덱스, 뷰테이블, 사용자정보 등 메타데이터를 저장하는 객체
MySQL,MsSQL등 다양한 RDBMS에는 데이터 타입이 존재합니다. JPA역시 Java의 데이터타입을 RDBMS와 매핑하기 위한 방법들이 존재합니다.
@Entity
@Table
public class Member{
@Id
@Column(name="ID")
private String id;
@Column(name="NAME")
private String username;
private Integer age;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemproalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description
}
데이터베이스 테이블과 필드를 매핑하기 위해 사용합니다.
속성
필드에 @Column을 사용하지 않으면, 모든 속성이 기본값으로 들어가게 된다.
Java Primitive type은 Null이 들어올 수 없으므로, DDL 생성 시 nullable=true로 설정됨
Wrapper Type을 사용하거나 nullable을 false로 지정해야 한다.
@Column(columnDefinition=”varchar(100)”) 과 같이, 방언정보를 활용해 선언한다
java의 날짜 타입인 java.util.Date, java.util.Calendar를 매핑한다.
속성
Java의 Date에는 날짜,시간이 모두 있지만, RDBMS는 date, time, timestamp로 나누어져있는 경우가 많아 @Temporal을 명시한 경우 value 속성을 필수로 지정해야한다.
@Temporal을 생략하면, DB의 timestamp 타입으로 매핑된다.
속성
EnumType.ORDINAL로 지정할 경우, 저장되는 크기가 작다는 장점이 있지만, 순서가 바뀌거나 사이에 새로운 내용이 추가되었을 때, 데이터베이스의 기존 데이터와 일치하지 않는다는 문제가 있다. 따라서, EnumType.STRING을 권장한다.
데이터베이스의 CLOB, BLOB 타입과 매핑됩니다. 필드 타입이 문자면 CLOB, 나머지는 BLOB로 매핑됩니다.
Example)
@Lob //문자 필드이므로 CLOB으로 매핑
private String lobString;
@Lob //문자필드가 아니므로 BLOB으로 매핑
private byte[] lobByte;
CLOB: Character Large Object (대형 문자 객체) , BLOB: Binary Large Object(대형 이진 객체)로, 최대 4GB의 대형 문자/이진 객체를 데이터베이스 시스템 밖의 파일로 저장하는 타입입니다.
@Transient가 지정된 필드는 데이터베이스에 저장하지 않고, 따라서 조회하지도 않습니다.
JPA가 엔티티 데이터에 접근하는 방식을 지정합니다.
@Id 의 위치에 따라, @id가 프로퍼티(getter)에 있으면, 자동으로 AccessType.PROPERTY에 지정, 필드에 있으면 AccessType.FIELD에 지정됩니다.
@Access //: 필드통한 접근
private Long Id
@Access //: 프로퍼티 통한 접근
public Long getId() {...}
내용들을 공부하기 전에 확인했던 엔티티입니다. 아래 엔티티를 확인하면, 필드에 선언된 애너테이션의 의미와 역할, 제한사항, 컬럼 등에 대해 이해할 수 있습니다.
@Entity
@Table
public class Member{
@Id
@Column(name="ID")
private String id;
@Column(name="NAME")
private String username;
private Integer age;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemproalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description
}
JPA는 위처럼 엔티티를 통해 데이터베이스 테이블이 어떻게 구성되는지 알 수 있습니다. 이를 통해 데이터베이스 스키마를 DDL(Data Definition Language)로 자동 생성해주는 기능을 갖습니다.
(show-sql은 실행되는 쿼리를 콘솔에 출력해줍니다.)
application.properties
spring.jpa.hibernate.ddl-auto: create
spring.jpa.show-sql: true
application.yaml
spring:
jpa:
show-sql: true
hibernate:
ddl-auto: create
옵션 | 환경 | 설명 |
---|---|---|
create | 개발 초기 | 기존 테이블을 삭제 후, 새로 생성 (DROP + CREATE) |
create-drop | 개발 초기 | 애플리케이션을 시작할 때 CREATE, 종료할 때 DROP (CREATE + DROP) |
update | 테스트서버 | 데이터베이스 테이블과 엔티티의 변경사항을 비교해 변경사항만 수정 |
validate | 테스트서버 or | |
스테이징/운영서버 | 데이터베이스 테이블과 엔티티 매핑정보가 차이가 있을 경우, 경고를 남기고 애플리케이션을 실행하지 않음. | |
none | 스테이징/운영서버 | 자동생성기능을 사용하지 않음. ddl-auto 옵션을 제거하거나 유효하지 않은 옵션을 준것과 같음 |
ddl-auto 옵션은 운영환경에서 사용할만큼 완벽하지 않다고 한다. 그렇기에 학습이나 참고용으로만 사용하는것이 좋다.
정답