ORM 표준 JPA 프로그래밍 - 엔티티 매핑

링딩·2022년 8월 27일
0

ORM 표준 JPA

목록 보기
3/6

김영한 강사님의 해당 강의를 통해 해당 글을 작성하였습니다.

들어가기 전에

엔티티 매핑 소개

• 객체와 테이블 매핑: @Entity, @Table
• 필드와 컬럼 매핑: @Column
• 기본 키 매핑: @Id
• 연관관계 매핑: @ManyToOne,@JoinColumn


객체와 테이블 매핑


@Entity

  • @Entity가 붙은 클래스는 JPA가 관리하는 엔티티
    -> 이게 안 붙으면 테이블과 관련 x
    => JPA를 사용해서 테이블과 매핑할 클래스는 필수

주의

기본 생성자가 필수이다. (파라미터x public 혹은 protected)
-> 구현해서 쓰는 기술들을 쓰려면 필요함.
final 클래스, enum, interface, inner 클래스 사용X
• DB에 저장할 필드에는 final 사용 X


속성: name

기본값 : 클래스 이름을 그대로 사용
ex) 다른 패키지에 같은 이름의 클래스가 있을 경우에 매핑까지 되어 있다면 구분해준다.
• 가급적 기본값을 사용해주자
구분지어줘야 할 때


@Table

• 엔티티와 매핑할 테이블을 지정해준다.

[그 외의 속성들]


데이터베이스의 스키마를 자동생성?

위치: .properties에 가서 hibernate.hbm2ddl.auto속성을 설정해 줄 수 있다.

DDL애플리케이션 실행 시점에 자동 생성
-> 객체 매핑을 다 해놓으면 애플리케이션이 뜰 때, 필요한 테이블을 다 만들어줌

• 테이블 중심 -> 객체 중심

• 데이터베이스 방언(ex 오라클(varchar2), mysql(varchar)등)을 무엇으로 생성했느냐에 따라서 데이터베이스에 맞는 적절한 DDL 생성

• 이렇게 생성된 DDL은 개발 장비에서만 사용
-> 절대 운영서버에서는 사용하지 (x)
=> 쓰고 싶다면 적절히 다듬은 후 사용하길...

[속성들]

  • 운영 장비에는 절.대. create, create-drop , update를 사용하면 안된다.
  • 개발 초기:
    create or update자기 로컬에서 쓰면 됨
  • 테스트 서버:
    update 혹은 validate
    -> 여러 개발자들과 함께 쓰는 곳일 경우에
    => 다른 개발자가 테스트 하는데 이거로,,데이터 다 날라갈 수 있다,,
  • 스테이징과 운영 서버: validate or none

주의

  • 직접 스크립트를 짜서 적용해보고 문제가 없으면 적용해보자
  • 결론: 로컬에서만 자유롭게 쓰고 여러명이 쓰는 곳에선 저런거를 쓰지말자
  • '스크립트' : SQL 문

DDL 생성 기능

@Table 같은 경우는 Runtime에 영향을 준다.
그러나 그 외에는 보면 ddl 생성기능에 제약조건을 주는 정도이다.
ex) @Column(nullable=false, length=10)

이런 것들을 DDL 생성기능이라 한다.

=> 곧 DDL을 자동 생성할 때만 사용되고, JPA 실행 로직에 영향을 주진 않는다...




필드와 컬럼 매핑

@Column

  • name : 테이블에 지정하고 싶은 이름
  • insertable, updatable
    : 말 그대로 등록/변경(수정) 가능 여부
    -> 그러나 jpa를 쓰면 반영(x)
  • nullable: 값의 허용 여부
    -> false 하면, DDL에서 not null이 된다.
  • unique
    - 한 컬럼에 간단히 제약조건을 걸 때 씀 (보통 컬럼에 잘 안 씀)
    -> 이름이 못 알아보게 나와서.. 반영이 힘듦.
    • @Table에 uniqueConstraints로 주면 이름 설정이 가능함.
  • columnDefinition
    - DB에 컬럼정보를 직접 줌.

@Enumerated

  • 자바 enum 타입을 매핑할 때 쓰임.
  • 주의: ORDINARL은 사용하지 말자!!!!🧨🤪

  • ordinal : enum의 순서를 DB에 저장

  • STRING: enum의 이름을 DB에 저장


@Temporal

  • 날짜 타입을 매핑할 때 사용.
  • 현재는 LocalDate, LocalDateTime 등의 타입이 더 많이 쓰인다..
    -> 물론 최신 하이버네이트에서 지원.

@Lob

주로 긴 글에서 많이 사용함.
• 데이터베이스 BLOB, CLOB 타입과 매핑
@Lob에는 지정할 수 있는 속성이 없다.
• 매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑
- CLOB: String, char[], java.sql.CLOB
- BLOB: byte[], java.sql. BLOB


@Transient

• 필드 매핑X , 데이터베이스에 저장X, 조회X
매핑을 하기 싫으면 이것을 쓰면 됨
• 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용



기본 키 매핑

• @Id
• @GeneratedValue
이렇게 2가지로 나뉘고 쓰인다.

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

이들은 매핑 방법을 통해서 나뉜다.

기본키 매핑 방법

• 직접 할당: @Id만 사용

• 자동 생성(@GeneratedValue)

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

[자동 생성]

1.IDENTITY 전략

[매핑]

• 기본 키 생성을 데이터베이스에 위임
• 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용
(예: MySQL의 AUTO INCREMENT)
• JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
• AUTO
INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있음
• IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행하고 DB에서 식별자를 조회

=> 나는 모르겠고 DB 니가 알아서 해라

내가 id에 값을 넣어서는 안된다. null로 날라오면 DB에서 값을 세팅해주어야 한다.
id값을 언제 알 수 있냐? DB에 값이 딱 들어왔을 때 알 수 있다.
영속성 컨텍스트에서 PK 값을 모르니까 울며 겨자먹기로

  • 딱 여기서만 예외적으로 em.persist() 를 호출하는 시점에 바.로. DB에 INSERT 쿼리를 날린다.
  • jpa가 내부적으로 이 id 값을 셀렉트해서 가져온다 .
  • 이 영속성 컨텍스트에 id 값이 빠르게 세팅,
    -> DB INSERT 하는 시점에 이 값을 알 수 있기 때문에

-> JPA가 그 값을 들고 와서 바로 세팅해주고 영속성 컨텍스트의 PK 값으로 쓰게 된다.

단점: 모아서 하는게 불가능


2. SEQUENCE 전략

'값'순서대로 생성하는 특별한 데이터베이스 오브젝트 -> 대표적으로 '오라클'이 있음.
ex) 오라클, PostgreSQL, DB2, H2 데이터베이스

@SequenceGenerator()을 어노테이션으로 설정하여 세세하게 설정

  • 이용: @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "적용하고자 하는 시퀀스 전략")

(동작)

call next value for
: DB에
에 다음 값 내놔라!

여기서 얻은 값을 em.persist()로 영속성 컨텍스트에 값을 넣으려고 딱 하는데

어 너? 시퀀스네? DB한테 값을 얻어와야겠네?

DB에서 값을 얻어와서 객체에 딱 id를 넣어주는 것이다!
=> 아직 INSERT 쿼리는 안 날라갔음 (왜? PK 값만 얻고 필요하면 버퍼링도 해줘야 하니까!!!)
=> 영속성 컨텍스트에 쌓여있음

이러고 PK 값을 얻고, 실제 커밋하는 시점에 INSERT 쿼리가 호출하게 된다.

특징: 버퍼링이 가능


[@SequenceGenerator 의 속성들]

이들을 이용해 성능 최적화에 쓰임.

allocationSize가 왜 50일까?

=> 자꾸 next.call()로 가져오면 성능 문제가 있을 수 있어
=> 그러니 그냥 난 DB를 50개 미리 땡겨올래!
=> 50에 거의 다 와가네 next.call() 1번 호출 -> 그러면 다시 한 번 더 51~100까지 땡겨오고

=> 곧 DB에 next call로 미리 세팅해놓고(50개씩) - 나는 메모리에서 1씩 쓰는 것이다.
여러 웹서버들이 있어도, 동시성 문제 없이 다양한 문제들이 해결되는 장점이 있다.


TABLE 전략

• 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
• 장점: 모든 데이터베이스에 적용 가능
• 단점: 성능


@TableGenerator - 속성

allocationSize: 미리 값을 올려두는 방식임.

  • 동시 호출을 하더라도 본인이 숫자를 미리 확보하엿기 때문에 문제x
profile
초짜 백엔드 개린이

0개의 댓글