Spring

3. 스프링 공부 / 2021-07-14 (필드와 컬럼 매핑 ~)

공대키메라 2021. 7. 14. 22:41

 

 필드와 컬럼 매핑 

package hellojpa;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(uniqueContraints = "testing")
//위에서 처럼 unique 키를 설정 시 이름을 선언 가능
public class Member {

    @Id // pk Mapping
    private long id;

    @Column(name = "name", insertable = true, updatable = true,nullable = false, unique =  true, length = 10
    , columnDefinition = "varchar(100) default 'EMPTY'"
    ) // column name 설정
    //insert할때 이 column을 반영할건지, update 할때 반영할건지 선택 가능
    //nullable을 이용해 null 여부 결정 가능
    //unique <= 제약조건 추가 는 잘 안씀!  => 제약 조건 이름이 이상하게 생성됨 
    //columnDefinition을 이용해서 크기 및 default값 설정 가능
    private String username;

    private int age;

    // @Enumerated(EnumType.STRING)DB에 사용할 수 있는 ENUM
    @Enumerated(EnumType.ORDINAL)
    private RoleType roleType;

	//TemporalType => DATE, TIME, TIMESTAMP
    @Temporal(TemporalType.TIMESTAMP) // 날짜 ENUM
    private Date createDate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastDate;

    @Lob
    private String description;

    public Member(){
    }

}

 

member 정보를 담은 클래스인 Member를 위와 같이 적어보았다.

 

그리고 이제 연결되어있는 main 을 실행시켜보려고 한다.

JpaMain.class는 다음과 같이 했다.

 

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

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){
            e.printStackTrace();
            tx.rollback();
        }finally {
            em.close();
        }

        emf.close();

    }
}

 

그러면 console창에 쿼리가 날아가는 것을 확인할 수 가 있다.

왜? 우리가 @Entity를 이용해서 class를 이미 table로 쓰겟다고 설정해놔서그럼!

 

Mapping Annotaion 정리

 

  • @Column  : 컬럼 매핑 
  • @Temporal : 날짜 타입 매핑
  • @Enumerated : enum 타입 매핑
  • @Lob : BLOC, CLOB 매핑
  • @Transient : 특정 필드를 컬럼에서 제외

 

RoleType의 ENUM 을 생성함.

package hellojpa;

public enum RoleType {
USER, ADMIN
}

근데 EnumType으로 Ordinal 은 하지 말라고함. 

왜 그러냐면RoleType을 주는데 ORDINAL로 설정하고서 이제 데이터를 넣어놧는데

역할이 추가되면 숫자가 뒤엉킴. 그럼 개발 망함

 

위에 RoleType 보면 USER 가 0 이 되고, ADMIN이 1이 된다

 

근데 앞에 하나를 더 추가하면 어떻게 될까?

 

public enum RoleType {
TEST, USER, ADMIN


}

TEST : 0 / USER : 1 / ADMIN : 2

 

그러므로 role 을 줄때는 String으로 주는게 좋다. => 겹치지 않음!

 

 

기본 키 매핑

 

우선 JpaMain은 이렇게 바꾸고,

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

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("ID_A");
            member.setUsername("A");

            em.persist(member);

            tx.commit();
        }catch(Exception e){
            e.printStackTrace();
            tx.rollback();
        }finally {
            em.close();
        }

        emf.close();

    }
}

 

Member.java Class도 이렇게 해본다.

package hellojpa;

import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;

@Entity
public class Member {

    @Id
    private String id;

    @Column(name = "name",  nullable = false)
    private String username;

    public Member(){
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

 

그러면 여기 테이블이 생성된 것을 확인할 수 있다. 

PK 설정시에는 보통 Sequence를 많이 사용한다. 

@id 처럼 직접 정해서 넣는게 아니라!

 

 

자동 생성은 그럼 어떻게 하나?

 

@GeneratedValue()를 쓴다. 

 

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  //GenerationType 에는  SEQUENCE, IDENTITY, AUTO가 있다. 
  private String id;

 

IDENTITY는  "나는 모르겟고 DB야 너가 알아서 넣어줘!"

 

SEQUENCE는 "db에 sequence만들어서 불러줘! " 

 

SEQUENCE로 설정해 주면 private long id; 로 해줘야겠지?

 

만약에 SEQUENCE를 미리 만들어 주고 싶다면...

 

@Entity
@SequenceGenerator(
	name = "MEMBER_SEQ_GENTERATOR",
    sequenceName = "MEMBER_SEQ" // 매핑할 데이터베이스 시퀀스 이름
    initialValue = 1, allocationSize = 1)
    
 public Class Member{
 	@Id
    @GenereatedValue(strategy = GenerationType.SEQUENCE,
    generator = "MEMBER_SEQ_GENERATOR")
    private Long id;
    
    ...이하 생략
 }

Table도 생성할 수 있는데 그건 알아서 해보길 바란다. (잘안쓰는건 안비밀 S2)

 

여기서 주목해야 할 INDENTITY의 특징은

tx.commit()을 하기 전에 em.persist(member)만 실행해도

쿼리가 나간다!

 

그 이유는 IDENTITY는 쿼리를 날려봐야 확인이 가능하기 때문이다.

 

SEQUENCE도 사실 DB에 접근을 해서 그 해당 SEQUENCE의 값을 가져와야 하기 때문에 

IDENTITY처럼 commit()전에 미리 쿼리를 날린다.