ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 엔티티 매핑 - 기본키 매핑
    김영한(인프런 강의)/자바 ORM 표준 JPA 프로그래밍 2020. 10. 5. 12:20
    반응형

    기본 키 매핑방법

    1. 직접할당(@ID)

    @Id
    private Long id;

    2. 자동생성(@GeneratedValue) 

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

     

    속성 이름
    IDENTITY 데이터베이스에 위임(자동할당), MYSQL
    SEQUENCE 데이터베이스 시퀀스 오브젝트 사용, ORACLE
       - @SequenceGenerator 필요
    TABLE 키 생성용 테이블 사용, 모든 DB에서 사용
       - @TableGenerator 필요
    AUTO 방언에 따라 자동 지정, 기본값

     

    기본적인 자동생성 속성은 위와같으며 자세히 알아보자

     

    자동생성 속성 특징

    1. IDENTITY 전략

     

    H2 DB로 실행했을 때
    MySQL로 실행했을 때

    @Entity
    public class Member {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id; 
    	Getter(), Setter() ....
    }

     

    3,4,5 설명

     

        1) 기본 키 생성을 데이터베이스에 위임

        2) 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용

            - MySQL의 AUTO_ INCREMENT

        3) JPA는 보통 트랜잭션 커밋 시점INSERT SQL 실행(먼저 INSERT SQL을 먼저 실행)

        4) AUTO_ INCREMENT는 데이터베이스에 INSERT SQL을 실행 한 이후에 ID 값을 알 수 있음

        5) IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행 하고 DB에서 식별자를 조회

     

    2. SEQUENCE 전략

    @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;
       
       Getter(), Setter() ...
    }

        1) 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트

        2) 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용

        3) @SequenceGenerator 속성

    속성 설명 기본값
    name 식별자 생성기 이름 필수
    sequenceName 데이터베이스에 등록되어 있는 시퀀스 이름 hibernate_sequence
    initialValue DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 1 시작하는 수를 지정한다. 1
    allocationSize - 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용됨)
    데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값 을 반드시 1로 설정해야 한다.
    - 실무에서는 50 또는 100을 잡아두고 사용한다. 만개씩 잡아두게 된다면 서버가 종료될 때 문제가 발생
    기본값은 50
    catalog, schema 데이터베이스 catalog, schema 이름  

     

    3. TABLE 전략

    @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; 
       
        Getter(), Setter()
    }

    위의 코드를 실행한다면 아래와 같이 table이 생성된다.

     

        1) 키 생성 전용 테이블을 하나 생성하여 데이터베이스 시퀀스를 흉내내는 전략

            - 장점 : 모든 데이터베이스에 적용 가능

            - 단점 : 성능(테이블을 직성 사용하다보니 lock 이슈 발생가능성, 숫자 생성에 최적화가 안되어있음) 

         2) @TableGenerator 속성

    속성 설명 기본값
    name 식별자 생성기 이름 필수
    table 키생성 테이블명 hibernate_sequences
    pkColumnName 시퀀스 컬럼명 sequence_name
    valueColumnNa 시퀀스 값 컬럼명 next_val
    pkColumnValue 키로 사용할 값 이름 엔티티 이름
    initialValue 초기 값, 마지막으로 생성된 값이 기준이다 0
    allocationSize 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용됨) 50
    catalog, schema 데이터베이스 catalog, schema 이름  
    uniqueConstraint s(DDL) 유니크 제약 조건을 지정할 수 있다.  

        3) allocationSize 설명

    public class JpaStudyApplication {
    
    	public static void main(String[] args) {
    		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    
    		EntityManager em = emf.createEntityManager();
    		
    		EntityTransaction tx = em.getTransaction();
    		
    		//트랜잭션 시작
    		tx.begin();
    		
    		try {
    			Member member = null;
    			
    			System.out.println("==========================================");
    			for(int i =1; i < 3; i++) {
    				member = new Member();
    				member.setUsername("Jin_Seok " + i);
    				em.persist(member);
    			}
    			
    			System.out.println("==========================================");
    			
    			tx.commit(); // [트랜잭션] 커밋
    		}catch (Exception e) {
    			tx.rollback();
    		}finally {
    			em.close();
    			
    		}
    		emf.close();
    	}
    }

    위의 코드일 때 SEQ번호

     

    public class JpaStudyApplication {
    
    	public static void main(String[] args) {
    		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    
    		EntityManager em = emf.createEntityManager();
    		
    		EntityTransaction tx = em.getTransaction();
    		
    		//트랜잭션 시작
    		tx.begin();
    		
    		try {
    			Member member = null;
    			
    			System.out.println("==========================================");
    			for(int i =51; i < 53; i++) {
    				member = new Member();
    				member.setUsername("Jin_Seok " + i);
    				em.persist(member);
    			}
    			
    			System.out.println("==========================================");
    			
    			tx.commit(); // [트랜잭션] 커밋
    		}catch (Exception e) {
    			tx.rollback();
    		}finally {
    			em.close();
    			
    		}
    		emf.close();
    	}
    }
    

     

    위의 코드일 때 SEQ번호

     

     

    • 위의 코드를 보듯이 allocationSize를 50개로 잡게 된다면 50개씩 시퀀스가 늘어난다.
    • 할당된 시퀀스 번호는 JPA 메모리상에서 사용가능하다. 
    • 사용하지 않는 시퀀스 번호는 무시한다.(50개씩 사용)
      • 101개를 넣게 된다면 150번까지 시퀀스를 할당받음

     

    4. 권장하는 식별자 전략

        1) 기본 키 제약 조건 : null 아님, 유일, 변하면 안된다

        2) 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체 키)를 사용하자

            - ex) 주민등록번호 - 현시점에 주민번호 저장을 안함

        3) 권장: Long형 + 대체키 + 키 생성전략 사용

     

     

    반응형
Designed by Tistory.