해당 내용은 인프런 김영한 강사님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'의 강의를 기반으로 작성했습니다.
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
클래스에
@Entity를 붙이면, JPA가 관리하는 클래스가 됨
-> 엔티티라고 함
final, enum, interface, inner 클래스는 매핑 불가final 사용 불가final클래스나 메서드가 문제가 되는가?1. 프록시 클래스 생성 불가
Hibernate는 엔티티 클래스의 서브클래스를 만들어야 함
하지만 클래스에 final이 선언되어 있으면 상속이 불가능하므로 Hibernate가 프록시 객체 생성 불가
2. 프록시 메서드 오버라이딩 불가
Hibernate는 Laze Loading 시 필요한 메서드를 오버라이드해야 함
하지만 메서드에 final이 선언되어 있으면 오버라이드할 수 없으므로 Lazy Loading이 미작동
이 부분은... 좀 더 공부해봐야 알 것 같다.
JPA에서 엔티티 클래스를 데이터베이스의 테이블과 매핑하기 엔티티와 매핑할 테이블 지정
엔티티는 Member인데, 테이블은 규정상 축약을 사용하여 tb_mbr이라든지... 할 때 사용...?
아직 감이 덜 온다.
@Entity
@Table(name = "users", schema = "public", catalog = "my_database")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
SELECT * FROM my_database.public.users;
@Entity
@Table(name = "users", schema = "public")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
SELECT * FROM public.users;
🤔 카탈로그와 스키마 설정 효과와 사용 시 주의사항
- 설정 효과
- JPA가 쿼리를 실행할 때 테이블 경로를 명확히 정의 -> 동일한 이름의 테이블이 여러 스키마나 카탈로그에 있을 경우 충돌 방지
- 다중 데이터베이스 또는 다중 스키마 환경에서 유용
- 사용 시 주의 사항
- 데이터베이스 설정 확인
- 데이터베이스 드라이버와 설정이 스키마 및 카탈로그 지원
- 권한 문제
- 사용 중인 데이터베이스 계정이, 설정된 스키마 및 카탈로그에 접근할 수 있는 권한이 있어야 함
- MySQL 주의
- MySQL에서는 스키마가 무시될 수 있으며, 대신 데이터베이스 이름(카탈로그) 사용
- MySQL에서는 스키마와 카탈로그가 동일한 개념으로 취급
@Table(uniqueConstraints = {
@UniqueConstraint(columnNames = {"email"})
})
UNIQUE제약 조건 정의@Table(indexes = {
@Index(name = "idx_user_email", columnList = "email")
})
@Entity와 @Table의 차이?
@Entity와 해당 클래스가 JPA에서 관리되는 엔티티임을 선언
-> JPA가 해당 클래스를 데이터베이스 테이블과 매핑할 수 있도록 지정
@Table은 엔티티 클래스와 데이터베이스 테이블 간의 세부적인 매핑 설정
-> 데이터베이스 테이블의 이름, 스키마, 카탈로그, 인덱스, 유니크 제약 조건 등 지정
CREATE 쿼리 자체도 나가지 않음JPA가 제공하는 엔티티와 테이블 간의 매핑 기본 동작과 DDL 생성 전략에 기반
@Entity 선언 시, JPA는 해당 클래스를 관리하게 되고,yml이나 properties파일에 DDL 생성 전략을 정의하는 설정 포함이 되어 있으면,그러니까 왜?
@Entity가 선언된 클래스를 "데이터베이스에 저장되어야 하는 객체"로 간주위에서 말했듯이 JPA가 매핑 정보만 보면 어떤 쿼리를 만들지, 어떤 테이블을 만들어야 할 지 알 수 있음.(로딩 시점에 DB의 테이블을 생성하는 기능을 지원)
VARCHAR2, MySQL에선 VARCHAR...이렇게 생성된 DDL은 개발 환경에서만 사용하고, 운영 서버에서는 다듬어서 사용하거나 사용하지 말 것
hibernate.hbm2ddl.auto
DROP + CREATEALTER 쿼리를 날림DROP, CREATE로 새로 생성)DROP하지만, 강사님 생각으로는,
@Column(name = "name")username)은 애플리케이션 코드에서 사용name)은 데이터베이스 테이블에서 사용private Integer age;Integer와 가까운 숫자 타입이 선택됨@Enumerated(EnumType.STRING)enum이 없기 때문에 @Enumerated를 씀@Temporal(TemporalType.TIMESTAMP)@Lob
enum은 varchar랑 매핑됨
clob은 큰 문자열
hibernate.hbm2ddl.auto
@Column
TRUE컬럼을 수정했을 때 이 컬럼을 반영할 건지 아닌지(쿼리가 나갈 건지 아닌지)
FALSE로 해두면 절대 변경되지 않음
FALSE로 설정하면, DDL 생성 시 NOT NULL 제약 조건이 붙음@Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용@Table에서 지정하는 게 나음
String 타입에만 사용double, float 타입에는 적용되지 않음@EnumeratedEnumType.ORDINAL: enum 순서를 데이터베이스에 저장EnumType.STRING: enum 이름을 데이터베이스에 저장EnumType.ORDINAL그러나 기본값인 ORDINAL로 쓰면 안 됨
enum 타입이 추가되었는데 기존 타입 앞에 놓이면, 순서가 바뀜
ex) 처음에는 ADMIN과 USER 만 이 순서로 타입이 지정되면 ADMIN = 0, USER = 1인데, GUESS가 ADMIN 앞에 쓰이면 GUESS = 0, ADMIN = 1, USER = 2가 되지만, 기존 레코드 데이터들은 바뀌지 않으므로 운영상 버그가 발생
-> STRING 타입을 사용할 것
@TemporalLocalDate, LocalDateTime 사용 시 생략 가능@LobCLOB, 나머지는 BLOB 매핑@Transient