영속성 컨텍스트에는 식별자가 존재해야한다 -> IDENTITY 전략은 커밋 시점에 INSERT하는게 아니라 em.persist() 한 시점에 INSERT SQL을 실행하여 식별자 가져옴
따라서 모아서 쿼리 쏘는 버퍼링 불가능
@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;
SEQUENCE : 데이터베이스 시퀀스 오브젝트 사용. ORACLE, PostgreSQL, DB2, H2
@SequenceGenerator 필요
allocationSize 속성 : 시퀀스 한 번 호출에 증가하는 수 설정 가능 <- 매번 쿼리를 날려 시퀀스를 올리는 것이 아닌 50개~100개 정도 미리 가져와서 시퀀스를 저장해놓고 사용
TABLE : 키 생성용 테이블 사용. 모든 DB
테이블로 시퀀스 흉내냄. 모든 DB에 적용 가능하지만 성능 문제.. 비추
@TableGenerator 필요
AUTO : 방언에 따라 자동 지정. 기본값
연관관계 매핑
테이블은 외래 키로 조인을 통해 연관된 테이블을 찾음
객체는 참조를 통해 연관된 객체를 찾음
이 차이를 극복하기 위한 매핑 필요
단방향 연관관계
JoinColumn 을 이용해 실제 테이블에 넣은 FK을 설정해준다.
ManyToOne : 다대일 관계로 매핑한다. ( 내가 다 )
OneToMany : 일대다 관계로 매핑한다. ( 내가 일 )
양방향 연관관계
테이블은 FK 하나로만 양방향 참조 가능
객체는 양쪽에서 참조를 가지고 있어야 양방향 참조 가능
객체에서 양방향 매핑을 하려면 ? 연관관계 주인 설정 필요 <- DB입장에서는 어느 값을 변경해야 FK 값을 변경시키지? 혼동이 생기기 때문
연관관계 주인 은 보통 테이블의 FK 위치에 따라서 설정함.
연관관계 주인은 외래키를 관리함 ( 등록, 수정 ). 반대쪽은 그저 조회만
주인이 아니면 mappedBy 속성으로 주인을 지정한다. (`mappedBy = "{주인의 필드명}")
양방향 연관관계에서 자주하는 실수
실수 1. 연관관계의 주인에 값을 입력하지 않고 역방향에 값을 입력
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("member1");
**//역방향(주인이 아닌 방향)만 연관관계 설정
team.getMembers().add(member);**
em.persist(member);
저장 시 저장이 잘 안되고 FK 값에 null이 들어가버림
Member member = new Member();
member.setUsername("member1");
em.persist(member);
Team team = new Team();
team.setName("TeamA");
//연관관계 주인에 값을 설정member.setTeam(team);
em.persist(team);
- 이러면 잘 들어감
- 객체지향적으로 생각해보면 객체 양쪽에 값을 넣어주는 것이 바람직하다.
- 연관관계 편의 메서드를 생성하자 ( 둘다 삽입하는 것을 까먹기 때문에 `changeTeam(Team team)` 같은 메서드를 정의해 안에서 두 작업을 다 해준다 )
```java
public void changeTeam(Team team){
this.team = team;
team.getMembers().add(this);
}
엔티티 매핑
@Entity
,@Table
@Column
@Id
@ManyToOne
,OneToMany
객체와 테이블 매핑
@Entity
Entity
필수name
속성 : JPA에서 사용할 엔티티 이름 설정 ( 기본값은 클래스 이름을 그대로 사용 )@Table
name
속성 : 매핑할 테이블 이름 ( 기본값은 엔티티 이름 사용 )catalog
속성 : 데이터베이스에 catalog 매핑 ( catalog? )schema
속성 : 추가적으로 넣고 싶은 schema 매핑uniqueConsraints
속성 : DDL 생성 시에 유니크 제약조건 생성스키마 자동 생성
hibernate.hbm2ddl.auto
: 데이터베이스 스키마 자동생성 - 속성create
: 기존 테이블 삭제 후 다시 생성 ( DROP + CREATE )create-drop
: create와 같으나 종료시점에 테이블 DROPupdate
: 변경분만 반영 ( 운영 DB에는 사용하면 안됨 )drop table
이 아닌alter table
하게 됨.validate
: 엔티티와 테이블이 정상 매핑되었는지만 확인none
: 사용하지 않음DDL 생성기능
@Column(unique = true, length = 10, nullable=false)
필드와 컬럼 매핑
@Id
: pk 매핑@Column
: 컬럼 매핑name
: 필드와 매핑할 컬럼 이름 설정insertable, updatable
: insert나 update 할건지 안할건지nullable
: null 허용여부unique
: 유니크 제약조건 넣을 수 있음. 하지만 제약조건 이름이 이상하게 들어가므로@Table
에서uniqueConstraints
로 설정해주는 것이 바람직함.columnDefinition
: 데이터베이스에 컬럼 정보를 직접 줄 수 있음length
: 문자 길이 제약조건 (String 타입에만 사용)@Enumerated(EnumType.STRING)
: JPA에서 enum 타입을 쓰고 싶을 때 사용. DB에는 enum 타입이 없기 때문에 해당 어노테이션을 사용.@Temporal
: Date 타입을 매핑할 때 사용DATE
,TIME
,TIMESTAMP
@Lob
: varchar를 넘어서는 굉장히 큰 정보를 넣고 싶을 때 사용 (clob, blob)@Transient
: DB에 상관없이 메모리에서만 사용할 때 사용할 때 사용.기본키 매핑
@Id
만 사용@GeneratedValue
사용기본키 매핑 전략
IDENTITY
: 데이터베이스에 위임. ( like autoIncrement )MySQL
,SQL Server
,DB2
,PostgreSQL
em.persist()
한 시점에 INSERT SQL을 실행하여 식별자 가져옴SEQUENCE
: 데이터베이스 시퀀스 오브젝트 사용.ORACLE
,PostgreSQL
,DB2
,H2
@SequenceGenerator
필요allocationSize
속성 : 시퀀스 한 번 호출에 증가하는 수 설정 가능 <- 매번 쿼리를 날려 시퀀스를 올리는 것이 아닌 50개~100개 정도 미리 가져와서 시퀀스를 저장해놓고 사용TABLE
: 키 생성용 테이블 사용.모든 DB
비추
@TableGenerator
필요AUTO
: 방언에 따라 자동 지정. 기본값연관관계 매핑
단방향 연관관계
JoinColumn
을 이용해 실제 테이블에 넣은 FK을 설정해준다.ManyToOne
: 다대일 관계로 매핑한다. ( 내가 다 )OneToMany
: 일대다 관계로 매핑한다. ( 내가 일 )양방향 연관관계
연관관계 주인
설정 필요 <- DB입장에서는 어느 값을 변경해야 FK 값을 변경시키지? 혼동이 생기기 때문연관관계 주인
은 보통 테이블의 FK 위치에 따라서 설정함.연관관계 주인
은 외래키를 관리함 ( 등록, 수정 ). 반대쪽은 그저 조회만mappedBy
속성으로 주인을 지정한다. (`mappedBy = "{주인의 필드명}")양방향 연관관계에서 자주하는 실수
실수 1. 연관관계의 주인에 값을 입력하지 않고 역방향에 값을 입력
Team team = new Team(); team.setName("TeamA"); //연관관계 주인에 값을 설정 member.setTeam(team); em.persist(team);
실수 2. 무한 루프를 조심하자
toString
,lombok
,json 자동생성 라이브러리
를 이용할때 무한 루프 발생될 가능성👉 lombok의 toString() 만드는 것은 쓰지 마라. 쓰려면 이런 내용은 빼고 써라. 👉 컨트롤러에는 Entity를 절대 반환하지 마라. 엔티티를 API로 반환하지 마라.
양방향 매핑 정리