ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JPA (3) - 엔티티 매핑
    카테고리 없음 2024. 1. 11. 12:10

     

     

    1. 객체와 테이블 매핑 

     

    1.1 Entity

     

    @Entity : JPA가 관리, 테이블과 매핑할 클래스는 Entity 필수 

                   - 기본 생성자 필수, final클래스, enum, interface, inner클래스에는 사용불가 

                   - 저장할 필드에 final 금지 

     

    Entity 속성 : name : JPA에서 사용할 엔티티 이름 지정 (기본값은 클래스 이름 그대로 -> 가급적 기본값 사용하자)

     

    1.2 @Table

     

    엔티티와 매핑할 테이블 지정 

     

    속성 : name : 매핑할 테이블 명 (기본값 엔티티 이름을 사용)

              catalog : DB catalog 매핑

              schema : DB scchema매핑 

              uniqueConstraints: DDL 생성 시 유니크 제약 조건 생성 

     

    * 앞으로 나올 DDL 속성은 테이블 생성시 한번만 사용됨

     

    2. 데이터 베이스 스키마 자동 생성 

     

    - DDL은 실행 시점에 자동 생성 

    - DB 방언 활용해서 적절한 DDL 생성

    - 위 DDL은 개발 장비에서만 사용하자! (약간 오류 있을 수 있어서 그대로 반영 x)

     

    속성

    > xml에 hibernate.hbm2ddl.auto에 적을 값임

     

    > create : 기본 테이블 삭제 후 다시 생성 (DROP + CREATE)

    > create-drop : create와 같으나 종료 시점에 테이블 DROP (테스트 후에 다 날려버리고 싶을 때)

    > update : 변경만 반영 (운영DB에서 사용 금지)

    > validate : 엔티티와 테이블 정상 매핑되었는지 확인 

    > none : 사용하지 않음 

     

    * 운영 장비에는 절대 create, create-frop, update 사용금지 -> validate정도만 사용하자 

     

    2.1 DDL 생성기능 

     

    제약조건 추가: @Column(nullable = false, length = 10)

    유니크 제약조선 추가 : @Table(uniqueConstraints = {@UniqueConstraint(name = "NAME_AGE_UNIQUE", columnNames = {"", ""})}

     

    *생성에만 영향 실행로직에 영향없음 

     

     

    3. 필드와 컬럼 매핑

     

    ex) 요구사항 

    1. 회원은 일반, 관리자

    2. 회원 가입과 수정일 필요 

    3. 회원을 설명할 수 있는 필드 -> 길이 제한 없음

     

    @Entity
    public class Member{
    
    
    	@Id 
        private Long id;
        
        @Cloumn(name="name") //컬럼 매핑
        private String username;
        
        private Integer age;
        
        @Enumerated(EnumType.STRING) //enum타입 매핑
        private RoleType 
        
        @Remporal(TemporalType.TIMESTAMP) //날짜매핑 -> JAVA 8부터는 LocalDateTime있어서 안쓴다함
        private Date createdDate;
        
        @Remporal(TemporalType.TIMESTAMP)
        private Date lastModifiedDate;
        
        @Lob //BLOC,CLOB매핑 
        private String desciption;
        
        //@Transinet : 필드를 컬럼에 매핑 안함
    
    }

     

     

    3.1 Column 속성

     

    name : 필드와 매핑할 테이블 칼럼 명  (기본 값 객체의 필드명)

    insertable,updatable : 등록 및 변경 가능 여부

    unllable(DDL) : null값 허용 여부 

    unique(DDL) : 유니크 제약조건 -> 근데 테이블에서 사용하는게 나음 

    columnDefinition(DDL) : DB 컬럼 정보를 직접 줄 수 있다. (필드의 자바 타입과 방언 정보 활용해서 넘김)

    length(DDL) : 문자 길이 제약조건 

    percisionscale(DDL) : BigDecimal 타입에서 사용 (BigInteger) percision은 소수점 제외한 전체 자릴수, scale은 소수의 자릿수 (double, float타입에는 적용x 아주 큰 숫자 혹은 정밀한 소수 다룰 때 사용)

     

    3.2 @Enuerated

     

    > value를 STRING으로 사용하자 무조건 (기본값은 ORDINAL임)

     

    3.3 @Lob

     

    CLOB : String, char[], java.sql.CLOB

    BLOB : byte[], java.sql.BLOB

     

    3.4 Transient 

     

    > 메모리 상에서만 임시로 보관하고 싶은 값만 저장

     

    4. 기본키 매핑 

     

    @Id 직접할당 , @GeneratedValue (자동생성) 사용한다.

     

    4.1GeneratedValue 

     

    IDENTITY : 데이터 베이스에 위임한다. MYSQL

    SEQUENCE : 데이터 베이스에 시퀀스 오브젝트 사용한다 (@SequenceGenerator 필요) ,ORACLE

    TABLE : 키 생성용 테이블 지정 (모든 DB에서 사용가능 @TableGenerator 필요 

    AUTO: 방언에 따라 자동 지정 (기본값)

     

     

    - IDENTITY 전략 

     >주로 MySQL, PostgreSQL, SQL Server에서 사용 (AUTO_INCREMENT)

     > JPA는 트랜잭션 커밋 시점에 INSERT SQL 실행

     > IDENTITY 전략은 em.persist()시점에 즉시 INSERT SQL 실행한다 (식별자 조회해야해서)

     

    * 영속성 컨텍스트에 보관되는 동안 기본키 값을 알아야 관리가능 DB에 이를 위임했으면, DB에 다녀와야해서...

     

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

     

    - SEQUENCE 전략

     

    > 오라클, PostgreSQL, DB2, H2에서 사용함 

    > DB에 시퀀스를 미리 불러와서 하나씩 쓰다가 시퀀시 범위 넘어가면 다시 받아옴 

     

    @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;
    }

     

    - name: 식별자 생성기 이름 

    - sequenceName : DB에 등록된 시퀀스명 (기본값은 하이버네이트의 시퀀스)

    - initialValue : DDL 생성시에만 사용 -> 시퀀스 생성할 때 처음 1로 시작하는 수 지정 

    - allocationSize : 시퀀스 한번 호출시 증가하는 수(최적화에 사용된다. ) DB 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 사용한다 (기본값은 50이다)

     

    *allocatotionSize는 한 트랜잭션 내에서 시퀀스 한번에 몇개씩 불러와서 사용할지 지정하는 것 

    따라서 크게 잡으면 DB접근횟수가 줄어들어서 좋은점은 있지만, 

    (기본값 50일때)  만약 트랜잭션1에서 저장하고 트랜잭션2에서 다시 저장하려고 부르면 -> 트랜잭션 2의 기본키는 51부터 시작함! 

     

    - TABLE 전략

     

     > 키 생성 전용 테이블을 만들어서 시퀀스 흉내내기 

    > 모든 DB에서 사용가능하지만, 성능이 딸림 

     

    @TableGenerator(
    	name = "GNETO",
        table = "MY_SEQ",
        pkColumnValue = "MEMBER_SEQ", allocationSize =1 )
    )
    
    public class Member{
    	
        @Id
        @GenratedValue(strategy = GenerationType.TABLE, generator = "GNETO")
        private Long id;
    
    }

     

    - pkColumnName: 시퀀스 테이블에 pk 컬럼명 (기본 sequence_name)

    - valueColumnName : 시퀀스 값 컬럼명 (기본 next_val)

    - pkColumnValue : 키로 사용할 값 이름 (기본 값 엔티티 명) 

    - uniqueConstraints(DDL) : 유니크 제약 조건 지정 가능 

     

     

    > 권장하는 식별자 전략 

     

    - 키본 키 제약 조건 : null 아님, 변화금지 

    - 미래까지 이조건을 만족하는 자연키 찾기 어렵다 대리키 사용하자 

    - 권장 : LONG형 + 대체키 + 키 생성전략 사용 

    * ai 나 시퀀스 object 사용하자 -> 때에 따라 uuid  (비지니스를 키로 끌고 오는 것은 권장하지 않음)

     

     

     

    *column에 length같은 건 남기는 걸 선호 (개발자가 테이블 보고 유추가능)

      제약조건은 @Table등에 적자 

      부트 사용시 하이버네이트 이름 전략 (관례) 직접 바꿀 수 있다!

     

    *이제 연관관계를 배워서 객체 설계를 테이블에 맞춘게 아니라, 그래프 탐색이 가능하도록 연관관계 매핑해보자

Designed by Tistory.