1. 객체와 테이블 매핑
@Entity
- @Entity가 붙은 클래스는 JPA가 관리하는 엔티티
- 기본 생성자 필수 - (jpa에서 프록싱할때 사용하는 등에 필요)
- final 클래스 enum, interface, inner 클래스는 사용이 불가능
- 저장할 필드에 final 사용 불가능
@Table
- 엔티티와 매핑할 테이블 지정
- 속성
1) name: 매핑할 테이블 이름
2) catalog: 데이터베이스 catalog 매핑
3) schema: 데이터베이스 schema 매핑
4) uniqueConstraints (DDL): DDL 생성 시에 유니크 제약 조건 생성
@Entity
@Table(name="Member")
public class Member2 { ~ }
2.데이터베이스 스키마 자동 생성
- DDL을 애플리케이션 실행 시점에 자동 생성
- 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL 생성
- 속성
1) create: 기존테이블 삭제 후 다시 생성 (DROP + CREATE)
1) create-drop : create와 같으나 종료시점에 테이블 DROP
1) update: 변경분만 반영
1) validate: 엔티티와 테이블이 정상 매핑되었는지만 확인
1) none: 사용하지 않음
(개발 초기 단계는 create 또는 update
테스트 서버는 update 또는 validate
스테이징과 운영 서버는 validate 또는 none)
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
- 데이터베이스 방언 설정으로 다르게 셋팅 가능
<property name="hibernate.hbm2ddl.auto" value="create" />
- DDL 생성 기능(자동 생성할 때만 사용 되고 실행로직에는 영향 x)
//@Column(name = "name", columnDefinition = "varchar(100) default 'EMPTY'", length = 300)
@Column(name = "name")
private String username;
- 유니크 제약 조건 추가
@Table(uniqueConstraints = {@UniqueConstraint( name = "NAME_AGE_UNIQUE",
columnNames = {"NAME", "AGE"} )})
필드와 컬럼 매핑
필드와 컬럼을 매핑에 사용하느 어노테이션 종류
@Column
//@Column(name = "name", columnDefinition = "varchar(100) default 'EMPTY'", length = 300)
@Column(name = "name")
private String username;
@Temporal
- 날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용
( LocalDate, LocalDateTime을 사용할 때는 생략 가능(최신 하이버네이트 지원))
@Temporal(TemporalType.TIMESTAMP)
private Date createDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
// LocalDate, LocalDateTime 의 경우 자동 매핑됨
private LocalDate testLocalDate;
private LocalDateTime testLocalDateTime;
@Enumerated
- 자바 enum 타입을 매핑할 때 사용
public enum RoleType {
USER, ADMIN;
}
// @Enumerated(EnumType.ORDINAL) - enum 의 순서를 저장 : enum 순서가 바뀌면 문제 생김 사용 x
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Lob
- 데이터베이스 BLOB, CLOB 타입과 매핑
- @Lob에는 지정할 수 있는 속성이 없음
- 매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑
CLOB: String, char[], java.sql.CLOB
BLOB: byte[], java.sql. BLOB
@Transient
private int temp;
@Transient
- 필드 매핑X
- 데이터베이스에 저장X, 조회X
- 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용
@Transient
private Integer temp;
기본 키 매핑
기본 키 매핑 어노테이션
직접 할당: @Id만 사용
자동 생성(@GeneratedValue)
IDENTITY: 데이터베이스에 위임, MYSQL
SEQUENCE: 데이터베이스 시퀀스 오브젝트 사용, ORACLE @SequenceGenerator 필요
TABLE: 키 생성용 테이블 사용, 모든 DB에서 사용 @TableGenerator 필요
AUTO: 방언에 따라 자동 지정, 기본값
@Id
// @GeneratedValue(strategy = GenerationType.AUTO) // AUTO : DB에 위임
// @GeneratedValue(strategy = GenerationType.IDENTITY) // IDENTITY : MySQL auto_increment
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER2_SEQ_GENERATOR") // SEQUENCE : Oracle 시퀀스 생성
private Long id;
실습 내용 전체 코드
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@Entity
@SequenceGenerator(name="MEMBER2_SEQ_GENERATOR", sequenceName = "MEMBER_SEQ", initialValue = 1, allocationSize = 50)
public class Member2 {
@Id
// @GeneratedValue(strategy = GenerationType.AUTO) // AUTO : DB에 위임
// @GeneratedValue(strategy = GenerationType.IDENTITY) // IDENTITY : MySQL auto_increment
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER2_SEQ_GENERATOR") // SEQUENCE : Oracle 시퀀스 생성
private Long id;
//@Column(name = "name", columnDefinition = "varchar(100) default 'EMPTY'", length = 300)
@Column(name = "name")
private String username;
//@Column(name = "age", updatable = false, insertable = false, nullable = false, unique = true)
private Integer age;
// @Enumerated(EnumType.ORDINAL) - enum 의 순서를 저장 : enum 순서가 바뀌면 문제 생김 사용 x
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
// LocalDate, LocalDateTime 의 경우 자동 매핑됨
private LocalDate testLocalDate;
private LocalDateTime testLocalDateTime;
@Lob
private String description;
@Transient
private int temp;
public Member2() {}
public Member2(Long id, String username, Integer age, RoleType roleType, Date createDate, Date lastModifiedDate, String description, int temp) {
this.id = id;
this.username = username;
this.age = age;
this.roleType = roleType;
this.createDate = createDate;
this.lastModifiedDate = lastModifiedDate;
this.description = description;
this.temp = temp;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public RoleType getRoleType() {
return roleType;
}
public void setRoleType(RoleType roleType) {
this.roleType = roleType;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Date lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Date;
public class MemberMappingTest {
public static void main(String[] args) {
// persistence.xml 의 persistence-unit 을 받아서 EntityManagerFactory 생성 - 하나만 생성해서 전체 어플리케이션 공유
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test02");
//EntityManagerFactory 에서 EntityManager 생성 - 쓰레드간에 공유 X (사용하고 버려야함)
EntityManager em = emf.createEntityManager();
// EntityManager 의 트랜잭션 받아옴
EntityTransaction tx = em.getTransaction();
// 트랜잭션 시작 - 모든 데이터 변경은 이 안에서 처리해야함
tx.begin();
try {
/*
// pk 전략이 IDENTITY 인 경우: 비영속 -> 영속이 되면 DB 에 Insert 를 하고 id 값을 가져옴
// pk 전략이 SEQUENCE 인 경우: 비영속 -> 영속이 되면 SEQUENCE 에서 id 값(next value)을 가져옴
Member2 member = new Member2();
System.out.println("======= before =======");
em.persist(member);
System.out.println(member.getId());
System.out.println("======= After =======");
*/
/*
// pk 전략이 SEQUENCE allocationSize 에 맞춰서 시퀀스를 미리 땡겨 옴
Member2 member1 = new Member2();
Member2 member2 = new Member2();
Member2 member3 = new Member2();
System.out.println("======= before =======");
em.persist(member1);
em.persist(member2);
em.persist(member3);
System.out.println(member1.getId());
System.out.println(member2.getId());
System.out.println(member3.getId());
System.out.println("======= After =======");
*/
// 트랜잭션 커밋
tx.commit();
} catch (Exception e){
// 롤백
tx.rollback();
} finally {
// EntityManager 닫음
em.close();
}
// EntityManagerFactory 닫음
emf.close();
}
}
Reference
자바 ORM 표준 JPA 프로그래밍 - 김영한님
'JPA & Querydsl > JPA' 카테고리의 다른 글
5. 고급 매핑 (0) | 2021.02.24 |
---|---|
4. 다양한 연관관계 매핑 (0) | 2021.02.24 |
3. 연관관계 매핑 기초 (0) | 2021.02.22 |
1. 영속성 관리 (0) | 2021.02.20 |
인텔리제이 자바 버전 변경 (0) | 2021.02.16 |