코드 그라데이션

엔티티 매핑 3 - 필드와 컬럼 매핑 본문

Spring/JPA 공부

엔티티 매핑 3 - 필드와 컬럼 매핑

완벽한 장면 2023. 8. 15. 01:20

요구사항 추가

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();
  }
}

이러면

0으로 출력

 

두 번째 사용자를 추가하면

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

728x90
Comments