코드 그라데이션
엔티티 매핑 3 - 필드와 컬럼 매핑 본문
요구사항 추가
1. 회원은 일반 회원과 관리자로 구분해야 한다.
2. 회원 가입일과 수정일이 있어야 한다.
3. 회원을 설명할 수 있는 필드가 있어야 한다. 이 필드는 길이 제한이 없다.
변경된 Member 클래스
일단
<property name="hibernate.hbm2ddl.auto" value="create" />
이 옵션을 살리고.
Member
@Entity
@NoArgsConstructor
public class Member {
@Id
private Long id;
@Column(name = "name") // db에는 name이라고 쓰고 싶을 때.
private String username;
private Integer age;
@Enumerated(EnumType.STRING) //DB에는 기본적으로 Enum 타입이 없다.
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
}
RoleType
public enum RoleType {
ADMIN, USER
}
그렇게 하고 JPAMain 살짝 바꾼 다음에 실행
JPAMain
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
실행 화면
drop table if exists Member CASCADE
01:15:16.150 [main] INFO org.hibernate.orm.connections.access - HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@5cad8b7d] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
01:15:16.157 [main] DEBUG org.hibernate.SQL -
create table Member (
id bigint not null,
age integer,
createdDate timestamp,
description clob,
lastModifiedDate timestamp,
roleType varchar(255),
name varchar(255),
primary key (id)
)
Hibernate:
create table Member (
id bigint not null,
age integer,
createdDate timestamp,
description clob,
lastModifiedDate timestamp,
roleType varchar(255),
name varchar(255),
primary key (id)
)
이런 코드가 등장.
매핑 어노테이션 정리
@Column
@Enumerated
실습
또 일단 <property name="hibernate.hbm2ddl.auto" value="create" /> 이걸
<property name="hibernate.hbm2ddl.auto" value="update" />로 바꿔놓고.
Member 클래스에도 약간의 수정을 거친 후
@Entity
@NoArgsConstructor
public class Member {
@Id
private Long id;
@Column(name = "name", nullable = false) // 여기
private String username;
private int age; // 여기
@Enumerated // 여기
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
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 getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
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;
}
}
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member = new Member();
member.setId(1L);
member.setUsername("A");
member.setRoleType(RoleType.USER);
em.persist(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
이러면
두 번째 사용자를 추가하면
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member = new Member();
member.setId(2L);
member.setUsername("B");
member.setRoleType(RoleType.ADMIN);
em.persist(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
결과는
이렇게 나온다.
그런데 왜 ORDINAL을 쓰면 안 되냐면,
사용자 타입에 갑자기 GUEST가 추가되었다고 하면,
RoleType
public enum RoleType {
GUEST, USER, ADMIN
// 갑자기 요구사항에 게스트 추가
}
JPAMain
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member = new Member();
member.setId(3L);
member.setUsername("C");
member.setRoleType(RoleType.GUEST);
em.persist(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
엉망진창 됨!!!!
운영상에서 해결할 수 없는 버그가 됨.
그래서 ORDINAL 대신에 다시 STRING으로 바꿔서 쓰면
@Enumerated(EnumType.STRING)
private RoleType roleType;
그리고 3개 다시 추가하고, 실행하면
ROLETYPE이 숫자가 아닌 문자로 들어가 있는 것을 확인하게 됨
제대로 된 확인을 위해
<property name="hibernate.hbm2ddl.auto" value="update" />
update로 바꾸고
Enum의 가운데에 BEST_USER라는 Enum을 추가하고, 멤버를 하나 더 넣으면
public enum RoleType {
GUEST, USER, BEST_USER, ADMIN
}
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Member member4 = new Member();
member4.setId(4L);
member4.setUsername("D");
member4.setRoleType(RoleType.BEST_USER);
em.persist(member4);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
결과는
엉킴이나 충돌 없이, 구분도 완벽하게 되는 것을 확인할 수 있음!
@Temporal
실습
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
private LocalDate testLocalDate; // 연 월만
private LocalDateTime testLocalDateTime; // 연 월 일 모두 포함.
실행해보면 (당연히 새 데이터타입 삽입을 위해 update를 create로 살짝 바꿔놓고)
이렇게 들어가는 것을 확인할 수 있음
최신버전을 쓰니까 이 방식대로 하자.
그래서 @Temporal을 잘 안 쓴다는 것.
@LOB
위에서 보면
문자니까 c랑 매핑된 것을 확인할 수 있었음.
@Transient
'Spring > JPA 공부' 카테고리의 다른 글
<보충설명> 기본키 매핑 (0) | 2023.08.16 |
---|---|
엔티티 매핑 4 - 기본키 매핑 (0) | 2023.08.16 |
엔티티 매핑 2 - 데이터베이스 스키마 자동 생성 (0) | 2023.08.15 |
엔티티 매핑 1 - 객체와 테이블 매핑 (0) | 2023.08.15 |
flush와 준영속 상태 (0) | 2023.08.14 |