[JPA 기본] 엔티티 매핑
포스트
취소

[JPA 기본] 엔티티 매핑

객체와 테이블 매핑

  • @Entity 어노테이션
    • 특징
      • @Entity가 붙은 클래스는 JPA가 관리한다.
      • @Entity가 붙은 클래스는 엔티티라고 부른다.
      • JPA를 사용해서 테이블과 매핑할 클래스는 @Entity가 필수다.
    • 속성
      • name
        • JPA에서 사용할 엔티티 이름
        • 기본값: @Entity를 지정한 클래스의 이름
        • 주의점
          • 같은 클래스 이름이 없으면 가급적 기본값을 사용한다. (★)
    • 주의점
      • 기본 생성자를 필수로 생성해야 한다. (파라미터가 없는 public/protected 생성자)
      • final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.
      • DB에 저장할 필드에는 final을 사용하면 안된다.
    • 예시
        @Entity
        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        public class Member {
            @Id
            private Long id;
            private String name; 
            private String tel;
        }
        
  • @Table 어노테이션
    • 특징
      • 엔티티와 매핑할 테이블 지정
    • 속성
      • name
        • 기본값 : 매핑할 테이블 이름 엔티티 이름을 사용
      • catalog
        • 데이터베이스 catalog 매핑
      • schema
        • 데이터베이스 schema 매핑
      • uniqueConstraints (DDL)
        • DDL 생성 시에 유니크 제약조건 생성
    • 제약조건 추가
      • 예시
            //NOT NULL, 최대 제한 13글자
            @Entity
            @Table(name = "T_MEMBER")
            @Data
            @NoArgsConstructor
            @AllArgsConstructor
            public class Member {
                @Id
                private Long id;
                private String name;
                @Column(nullable = false, length = 13)
                private String tel;
            }
            
            //유니크 제약조건 추가
            @Entity
            @Table(
                name = "T_MEMBER",
                uniqueConstraints = {
                    @UniqueConstraint(
                        name = "NAME_TEL_UNIQUE",
                        columnNames = {
                            "NAME",
                            "TEL"
                        }
                    )
                }
            )
            @Data
            @NoArgsConstructor
            @AllArgsConstructor
            public class Member {
                @Id
                private Long id;
                private String name;
                private String tel;
            }
            

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

  • DDL을 애플리케이션 실행 시점에 자동 생성
  • 테이블 중심 -> 객체 중심
  • 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL 생성
  • 이렇게 생성된 DDL은 개발 장비에서만 사용
  • 생성된 DDL은 운영서버에서는 사용하지 않거나, 적절히 다듬은 후 사용
  • DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.

  • 생성 방법
    • properties 지정
      • hibernate.hbm2ddl.auto
        • 옵션
          • create
            • 기존테이블 삭제 후 다시 생성 (DROP + CREATE)
            • 위험도가 크니 로컬에서만 사용하기 (★)
          • create-drop
            • create와 같으나 종료시점에 테이블 DROP
            • 위험도가 크니 로컬에서만 사용하기 (★)
          • update
            • 변경분만 반영
            • 칼럼을 추가하는 경우에는 경우면 모를까 삭제할 때는 사용하면 안됨
            • 위험도가 크니 로컬에서만 사용하기 (★)
            • 왠만하면 직접 작성하는 것을 권장한다.
          • validate
            • 엔티티와 테이블이 정상 매핑되었는지만 확인
            • 개발 서버나 스테이징 서버에서 허용가능한 범위
          • none
            • 사용하지 않음
            • 관례상 명시 (★)
  • 주의점
    • 운영 장비에는 절대 create, create-drop, update를 사용하면 안 된다. (★)
    • 개발 초기 단계는 create 또는 update (로컬의 경우 ★)
    • 개발/스테이징/운영 서버는 validate 또는 none
      • 이유 : 여러 개발자가 공유하는 DB 서버의 경우에 문제가 발생할 수 있기 때문이다.
    • 직접 스크립트를 짜서 개발/스테이징에 적용을 하고
      문제가 없으면 DBA한테 검수를 받고 운영에 반영하는 것을 권장한다.
    • DDL에 대한 권한 자체가 없는 계정으로 돌아가도록 하는게 좋다. (★)

필드와 컬럼 매핑

  • 매핑 어노테이션
    • @Column
      • 역할
        • 컬럼 매핑
      • 속성
        • name
          • 필드와 매핑할 테이블의 컬럼 이름 객체의 필드 이름
          • 기본값 : 객체의 필드 이름
        • insertable
          • 등록 가능 여부
          • 기본값 : TRUE
        • updatable
          • 변경 가능 여부
          • 기본값 : TRUE
        • nullable
          • null 값의 허용 여부
          • false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다.
          • DDL용
        • unique
          • @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다.
          • DDL용
          • 제약조건명이 랜덤으로 생성되서 잘 쓰지는 않는다.
        • columnDefinition
          • 데이터베이스 컬럼 정보를 직접 줄 수 있다.
          • 필드의 자바 타입과 방언 정보를 사용해서 작성하기
          • DDL용
          • 예시
            • @Column(columnDefinition="varchar(100) default 'TEMP'")
            • @Column(columnDefinition = "MEDIUMTEXT")
        • length
          • 문자 길이 제약조건
          • String 타입에만 사용한다.
          • 기본값 : 255
          • DDL용
        • precision & scale
          • 종류
            • precision
              • 소수점을 포함한 전체 자릿수
              • 기본값 : 19
            • scale
              • 소수의 자릿수
              • 기본값 : 2
          • BigDecimal/BigInteger도 타입에서 사용한다.
          • double, float 타입에는 적용되지 않는다.
          • 정밀한 소수를 다루어야 할 때만 사용한다.
    • @ColumnDefault
      • 역할
        • 기본값 설정
      • 예시
        • @ColumnDefault("'Y'")
    • @Comment
      • 역할
        • 해당 칼럼의 설명을 설정
      • 예시
        • @Comment("이름")
    • @Enumerated
      • 역할
        • enum 타입 매핑
      • 속성
        • value
          • EnumType.ORDINAL
            • enum 순서를 데이터베이스에 저장
            • 코드를 중간에 작성하면 나중에 큰일난다.
            • 절대 사용하면 안 된다. (★)
          • EnumType.STRING
            • enum 이름을 데이터베이스에 저장
            • 절대 권장 (★)
    • @Temporal
      • 역할
        • 날짜 타입 매핑
          • java.util.Date
          • java.util.Calendar
      • 속성
        • value
          • TemporalType.DATE
            • 날짜
            • 데이터베이스 date 타입과 매핑
            • 예시 : 2013–10–11
          • TemporalType.TIME
            • 시간
            • 데이터베이스 time 타입과 매핑
            • 예시 : 11:11:11
          • TemporalType.TIMESTAMP
            • 날짜와 시간
            • 데이터베이스 timestamp 타입과 매핑
            • 예시 : 2013–10–11 11:11:11
      • 참고사항
        • : LocalDate, LocalDateTime을 사용할 때는 생략 가능 (최신 하이버네이트 지원)
    • @Lob
      • 역할
        • BLOB, CLOB 매핑
      • @Lob에는 지정할 수 있는 속성이 없다.
      • 매핑하는 필드 타입에 따라서 적용유형이 다르다.
        • BLOB
          • byte[]
          • java.sql.BLOG
        • CLOB
          • String
          • char[]
          • java.sql.CLOB
    • @Transient
      • 특정 필드를 컬럼에 매핑하지 않음 (매핑 무시)
      • 계산용 데이터나 캐시 데이터용으로 사용
  • 사용 예시
    @Entity
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Member { 
        @Id 
        private Long id;

        @Column(name = "name") 
        private String username;

        private Integer age; 
        @Enumerated(EnumType.STRING) 
        private RoleType roleType;

        @Temporal(TemporalType.TIMESTAMP) 
        private Date createdDate;

        @Temporal(TemporalType.TIMESTAMP) 
        private Date lastModifiedDate;

        @Lob 
        private String description;
    }
    

기본 키 매핑

  • @Id 어노테이션
    • 기본 키를 명시할 때 사용
  • @GeneratedValue 어노테이션
    • 자동으로 키 값을 지정할 때 사용
    • @Id 어노테이션과 함께 사용해야 한다.
    • 자동 생성에 대한 식별자 전략 방법에 따라 사용방법이 다르다.

식별자 전략

  • IDENTITY 전략
    • 기본 키 생성을 데이터베이스에 위임한다.
    • 주 사용처
      • MySQL
      • PostgreSQL
      • SQL Server
      • DB2
    • JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행한다.
    • DB에 INSERT SQL을 실행 한 이후에 ID 값을 알 수 있다.
    • em.persist() 시점에 즉시 INSERT SQL 실행하고 DB에서 식별자를 조회한다.(★)
    • 트랜잭션을 계속 잘라내면 성능에 문제가 크지만,
      한 트랜잭션 안에서 INSERT 쿼리가 네트워크 몇 번 더 탄다고
      성능이 비약적으로 차이가 나지는 않는다.
    • 사용예시
        @Entity 
            public class Member { 
            @Id 
            @GeneratedValue(strategy = GenerationType.IDENTITY) 
            private Long id;
        }
        
  • SEQUENCE 전략
    • 데이터베이스 시퀀스 오브젝트 사용
      • 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
    • 주 사용처
      • ORACLE
      • PostgreSQL
      • DB2
      • H2
    • @SequenceGenerator 필요
      • 속성
        • name
          • 식별자 생성기 이름
          • 필수
        • sequenceName 데이터베이스에 등록되어 있는 시퀀스 이름
          • 기본값 : hibernate_sequence
        • initialValue
          • 시퀀스 DDL을 생성할 때 처음 시작하는
          • DDL 생성 시에만 사용한다.
          • 기본값 : 1
        • allocationSize
          • 시퀀스 한 번 호출에 증가하는 수
          • 기본값 : 50
          • 시퀀스 값이 1씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다. (★)
        • catalog
          • 데이터베이스 catalog 이름
        • schema
          • 데이터베이스 schema 이름
    • 사용예시
        @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;
        }
        
  • TABLE 전략
    • 키 생성용 테이블 사용
    • 모든 DB에서 사용가능
    • 성능이 별로다.
    • @TableGenerator 필요
      • 속성
        • name
          • 식별자 생성기 이름
          • 필수
        • table
          • 키생성 테이블명
          • 기본값 : hibernate_sequences
        • pkColumnName
          • 시퀀스 컬럼명
          • 기본 값: sequence_name
        • valueColumnName
          • 시퀀스 값 컬럼명
          • 기본값 : next_val
        • pkColumnValue
          • 키로 사용할 값 이름
          • 기본값 : 엔티티 이름
        • initialValue
          • 초기 값
          • 마지막으로 생성된 값이 기준이다.
          • 기본값 : 0
        • allocationSize
          • 시퀀스 한 번 호출에 증가하는 수
          • 기본값 : 50
        • catalog
          • 데이터베이스 catalog 이름
        • schema
          • 데이터베이스 schema 이름
        • uniqueConstraints
          • 유니크 제약조건을 지정
          • DDL용
    • 사용예시
        @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; 
        }
        
  • AUTO 전략
    • DB 종류에 따라 자동 지정
    • 기본값
  • 권장하는 식별자 전략
    • 기본 키 제약조건
      • null 아님
      • 유일
      • 불변
    • 미래까지 기본 키 제약조건을 만족하는 자연키는 찾기 어렵다.
      • 대리키(대체키)를 사용 권장
        • 예시
          • UUID
    • 권장사항
      • Auto Increment
      • Sequence Object
      • Long형 + 대체키 + 키 생성전략 사용
  • SEQUENCE 전략의 특이성
    • allocationSize를 큰 숫자로 쓰게 된다면 한 번 읽을 때
      그 개수만큼 DB에 미리 올려놓고 사용할 수 있다.
    • 여러 웹 서버가 있어도 동시성 이슈 없이 다양한 문제들을 해결해준다.

출처

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.