객체와 테이블 매핑
@Entity
- @Entity가 붙은 클래스 → JPA가 관리하는 엔티티
- JPA를 사용하여 테이블과 매핑할 클래스는 필수!
- 주의
- 기본 생성자 필수 (파라미터가 없는 public or protected 생성자)
- final 클래스, enum, interface, inner 클래스 사용 x
- 속성 : name
- JPA에서 사용할 엔티티 이름을 지정 (기본값 : 클래스 이름)
@Table
엔티티와 매핑할 테이블 지정
name → 매핑할 테이블 이름 : @Table(name = “MBR”)
데이터베이스 스키마 자동 생성
- DDL을 애플리케이션 실행 시점에 자동 생성
- 테이블 중심 → 객체 중심
- 데이터베이스 방언을 활용하여 데이터베이스에 맞는 적절한 DDL 생성
- 이렇게 생성된 DDL은 개발 장비에서만 사용(운영서버 사용 x or 다듬은 후 사용)
속성
persistence.xml → hibernate.hbm2ddl.auto
- 옵션
- 주의
운영 장비에는 절대 create, create-drop, update 사용 x
개발 초기 단계 → create or update
테스트 서버 → update or validate
스테이징, 운영서버 → validate or none 되도록이면 none 사용 → 위험요소
테스트 서버, 개발서버 → validate까지는 괜찮음
- DDL 생성 기능
제약조건 추가 : 회원 이름은 필수, 10자 초과 x
→ @Column(nullable = false, length = 10)
DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향 x
필드와 컬럼 매핑
- 요구사항
- 회원은 일반 회원과 관리자로 구분
- 회원 가입일과 수정일 있어야 함
- 회원을 설명할 수 있는 필드가 있어야 함 -> 길이제한 없음
Member class
@Entity
public class Member {
@Id //pk 매핑
private long id;
@Column(name = "name") //객체는 username DB에는 name
private String username;
private Integer age;
@Enumerated(EnumType.STRING) //객체에서 EnumType 쓰고 싶을 때 DB에는 없을 때 enum 타입 매핑
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP) //날짜 타입 매핑(DB에서는 날짜, 시간, 날짜+시간 구분->TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
private LocalDate testlocaldate;
private LocalDateTime testlocaldatetime;
@Lob // DB에 큰 컨텐츠를 넣고 싶을 때 BLOB, CLOB 매핑
private String description;
@Transient // 특정 필드를 컬럼에서 제외
private int temp;
매핑 어노테이션 정리
@Column
@Enumerated
자바 enum 타입을 매핑할 때 사용
- EnumType.ORDINAL : enum의 순서를 DB에 저장 → 위험!
- EnumType.STRING : enum 이름을 DB에 저장
주의 ORDINAL 사용 x @Enumerated(EnumType.STRING) 이렇게 쓰기!
@Temporal
날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용
LocalDate, LocalDateTime를 사용할 때는 생략 가능 → 최신 하이버네이트 지원
private LocalDate testlocaldate;
private LocalDateTime testlocaldatetime; // 최신버전이면 이렇게 하면 됨
@Lob
@Lob에는 지정할 수 있는 속성이 없다.
매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑
@Transient
필드 매핑x, 데이터베이스에 저장x, 조회x
주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용
기본 키 매핑
- 기본 키 매핑 방법
- 직접할당 - @Id만 사용
- 자동 생성(@GeneratedValue)
자동 생성(@GeneratedValue)
1. IDENTITY 전략
- 기본 키 생성을 데이터베이스에 위임, MYSQL
- 주로 MYSQL, PostgreSQL, SQL Server, DB2에서 사용
- JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
- em.persist(member); 시점에 즉시 INSERT SQL 실행하고 DB에서 식별자 조회
- AUTO_INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있음
- 모아서 INSERT하는 것 불가능한 것이 단점
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // id Long타입으로 쓰기
}
2. SEQUENCE 전략
- 데이터베이스 시퀀스 오브젝트 사용
- 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
- 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용
@Entity
@SequenceGenerator(
name = “MEMBER_SEQ_GENERATOR",
sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
}
@SequenceGenerator
3. TABLE 전략
- 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
- 장점 : 모든 데이터베이스에 적용 가능
- 단점 : 성능
create table MY_SEQUENCES (
sequence_name varchar(255) not null,
next_val bigint,
primary key ( sequence_name )
)
@Entity
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = “MEMBER_SEQ", allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
}
@TableGenerator
4. 권장하는 식별자 전략
- 기본 키 제약 조건 : null 아님, 유일, 변하면 안된다.
- 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자
- 주민등록번호도 기본 키로 적절 x
- 권장 : Long형 + 대체키 + 키 생성전략 사용
실전 예제 1. 요구사항 분석과 기본 매핑
요구사항 분석
- 회원은 상품을 주문할 수 있다.
- 주문 시 여러 종류의 상품을 선택할 수 있다
기능 목록
- 회원 기능
- 회원 등록
- 회원 조회
- 상품 기능
- 상품등록
- 상품수정
- 상품조회
- 주문 기능
- 상품 주문
- 주문 내역 조회
- 주문 취소
도메인 모델 분석
- 회원과 주문의 관계 : 회원은 여러 번 주문할 수 있다. (일대다)
- 주문과 상품의 관계 : 주문할 때 여러 상품을 선택할 수 있다. 반대로 같은 상품도 여러 번 주문될 수 있다.
- 주문상품이라는 모델을 만들어서 다대다 관계를 일대다, 다대일 관계로 풀어냄
테이블 설계
엔티티 설계와 매핑
Item.class
@Entity
public class Item {
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
private int stockQuantity;
}
Member.class
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
private String city;
private String street;
private String zipcode;
}
Order.class
@Entity
@Table(name = "ORDERS")
public class Order {
@Id @GeneratedValue
@Column(name = "ORDER_ID")
private Long id;
@Column(name = "MEMBER_ID")
private Long memberId;
private Member member;
public Member getMember() {
return member;
}
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus status;
}
OrderItem.class
@Entity
public class OrderItem {
@Id @GeneratedValue
@Column(name = "ORDER_ITEM_ID")
private Long id;
@Column(name = "ORDER_ID")
private Long orderId;
@Column(name = "ITEM_ID")
private Long itemId;
private int orderPrice;
private int count;
}
OrderStatus.enum
package jpabook.jpashop.domain;
public enum OrderStatus {
ORDER,CANCEL
}
데이터 중심 설계의 문제점
- 현재 방식은 객체 설계를 테이블 설계에 맞춘 방식
- 테이블의 외래키를 객체에 그대로 가져옴
- 객체 그래프 탐색이 불가능
- 참조가 없으므로 UML도 잘못됨
참고 강의 :
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런
www.inflearn.com
'JPA > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 5. 연관관계 매핑 기초(2) (0) | 2022.12.29 |
---|---|
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 5. 연관관계 매핑 기초(1) (0) | 2022.12.28 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 3. 영속성 관리 (0) | 2022.11.29 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 2. JPA 시작 (0) | 2022.11.28 |
[자바 ORM 표준 JPA 프로그래밍 - 기본편] 1. JPA 소개 (0) | 2022.11.27 |