woowacourse-study / 2022-jpa-study

🔥 우아한테크코스 4기 JPA 스터디 (22.06.13~22.07.02) 🔥
5 stars 1 forks source link

[섹션 4, 섹션 5] 토르 제출합니다 #8

Closed injoon2019 closed 2 years ago

injoon2019 commented 2 years ago

4. 엔티티 매핑

엔티티 매핑

1. @Entity

테이블과 매핑할 클래스에 붙여야 한다.

2. @Table

엔티티와 매핑할 테이블을 지정한다.

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

persistence.xml에서 속성을 변경하면 애플리케이션 실행 시점에 데이터베이스 테이블을 어떻게 할지 지정해줄 수 있다. 하지만 스키마 자동 생성 기능이 만든 DDL이 운영 환경에서 쓸만큼 완벽하지는 않으니 참고용으로만 사용하자.

운영 서버에서는 create, crate-drop, update 같은 옵션은 절대 사용하지말자.

기본 키 매핑

1. IDENTITY 전략

MySQL에서 사용. 데이터베이스에 값을 저장하고 나서야 기본 키 값을 구할 수 있다. insert하고 get을 하는 방식으로 id를 구하지 않고 Statement.getGeneratedKeys()를 사용해서 저장하면서 동시에 생성된 키 값을 얻어온다.

영속 상태가 되려면 반드시 식별자가 필요한데, IDENTITY 전략은 데이터베이스에 저장해야 식별자를 구할 수 있으므로 em.persist()를 호출하는 즉시 INSERT SQL이 데이터베이스에 전달된다.

2. SEQUENCE 전략

시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트다. 오라클, H@가 사용한다.

em.persist()를 호출할 때 데이터베이스 시퀀스를 사용해서 식별자를 조회한 후 엔티티에 할당하고 엔티티를 영속성 컨텍스트에 저장한다.

시퀀스에 접근하는 횟수를 줄이기 위해 디폴트로 50개씩 가져와서 할당한다.

3. TABLE 전략

키 생성 전용 테이블을 만들고 시퀀스를 흉내내는 전략이다. 모든 DB에 적용할 수 있지만 성능이 좋지 않다.

필드와 컬럼 매핑: 레퍼런스

1. @Column

int 타입이면 JPA가 not null 제약 조건을 추가한다. 하지만 @Column을 사용하면 nullable = true가 기본값이므로 not null 제약조건을 직접 걸어줘야 한다.

2. @Enumerated

EnumType.STRING을 써야 enum이 추가되어도 안전하다.

3. @Transient

디비 컬럼과 매핑하지 않고 서버 메모리에서만 사용

5. 연관관계 매핑 기초

단방향 연관관계

참조를 통한 연관관계는 언제나 단방향이다. 양쪽에서 참조하는 것은 양방향이 아니라 서로 다른 단방향 관계 2개다.

1. @JoinColumn

@JoinColumn(name="TEAM_ID") 조인 컬럼은 외래 키를 매핑할 때 사용한다. name 속성에는 매핑할 외래 키 이름을 지정한다. 참고로 @JoinColumn을 생략하면 외래 키를 찾을 때 기본 전략을 사용한다. 필드명_참조하는 테이블의 컬럼명

회원 엔티티

@Entity
public class Member {
    @Id
    @Column(name = "MEMBER_ID")
    private String id;

    private String username;

    @ManyToOne
    @JoinColumn(name="TEAM_ID")
    private Team team;
    ...

팀 엔티티

@Entity
public class Team {
    @Id
    @Column(name = "TEAM_ID")
    private String id;

    private String name;
    ...
}

회원과 팀 저장

Team team1 = new Team("team1", "팀1");
em.persist(team1);

Member member1 = new Member("member1", "회원1");
member1.setTeam(team1);
em.persist(member1);

...

JPA는 참조한 팀의 식별자를 외래키로 사용해서 적절한 등록 쿼리를 작성한다. SQL을 보면 회원 태이블의 외래 키 값으로 참조한팀의 식별자 값인 team1이 입력된 것을 알 수 있다.

양방향 연관관계 매핑

JPA에서는 두 객체 연관관계 중 하나를 정해서 테이블의 외래키를 관리해야 한다. 이걸 연관관계의 주인이라 한다.

연관관계의 주인만이 데이터베이스 연관관계와 매핑되고 외래 키를 관리(등록, 수정 , 삭제)할 수 있다. 주인이 아닌 쪽은 읽기만 할 수 있다.

연관관계의 주인은 외래 키가 있는 곳으로 해야 한다. (사실 없는 쪽에 하면 전혀 다른 테이블에 쿼리가 날라가서 보기 힘들다고 하는데 이 부분 이해가 잘 안됐다. 나중에 얘기 나눠볼 것)

다대일, 일대다 관계에서는 항상 다 쪽이 외래키를 가진다.

양방향 관계는 객체 관점에서 양쪽 방향에 모두 값을 입력해주는게 바람직하다. 그래야 JPA가 없는 상황에서 문제가 발생하지 않는다.