woowacourse-study / 2022-jpa-study

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

[섹션 4, 섹션 5] 헌치 제출합니다 #11

Closed BETTERFUTURE4 closed 2 years ago

BETTERFUTURE4 commented 2 years ago

섹션 4 : 엔티티 매핑

4-1 객체와 테이블 매핑

객체와 테이블을 매핑한다

1) @Entity

JPA를 통해 테이블과 매핑할 클래스는 @Entity가 필수

2) @Table

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

name 속성 : 매핑할 이름 지정(기본값 엔티티 이름)

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

DDL을 애플리케이션 실행 시점에 자동 생성

1) DDL

2) DDL 자동생성 기능

DB 중심 -> 객체 중심

3) 속성

4) 주의사항

운영장비에서는 create, update 쓰지마라!!!

4-3 필드와 컬럼 매핑


import java.beans.Transient;

@Entity
public class Member {
    @Id
    private Long id;

    @Column(name = "name") // 해당 이름으로 칼럼 매핑
    private String username;

    private Integer age; // 생각한대로 매핑됨

    @Enumerated(EnumType.STRING) // enum 타입 지정
    private RoleType roleType;

    @Temporal(TemporalType.TIMESTAMP) //날짜 매핑(TIMESTAMP : 날짜+시간)
    private Date createdDate;

    @Lob // 큰 컨텐츠(BLOB, CLOB 등)
    private String description;

    @Transient // 매핑에 사용 X
    private int temp;
}

1) @Id

기본 키(PK)를 매핑한다

2) @Column

필드와 컬럼을 매핑한다

설정

3)@Enumerated

EnumType.STRING을 사용하자!

4) @Temporal

날짜 타입(Date, Calendar 유틸) 매핑

LocalDate, LocalDateTime을 사용할 때는 생략 가능

5) @Lob

DB BLOB(문자X), CLOB(문자) 타입과 매핑

6) @Transient

필드 매핑X

7) @ManyToOne, @JoinColumn

연관관계를 매핑한다

4-4 기본키(PK) 매핑

1) @Id

직접 할당

2) @GeneratedValue

자동 생성

3) IDENTITY 전략

기본 키 생성을 데이터베이스에 위임

class Member {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer id;
}

MySQL의 AUTO_ INCREMENT 등에서 사용

AUTO_ INCREMENT : DB에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있음

4) SEQUENCE 전략

class Member {
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(
            name = "MEMBER_SEQ_GENERATOR",
            sequenceName = "MEMBER_SEQ", // 매핑할 데이터베이스 시퀀스 이름
            initialValue = 1, allocationSize = 50)
    public Integer id;
}

allocationSize : 한번에 50개의 인덱스 가져옴(테이블 전략에서도 사용)

5) 권장하는 식별자 전략

Long 형태

대체키 사용

키 생성 전략(auto-increment)

PK 제약조건 : null 아님, 유일, 불변

섹션 5 : 연관관계 매핑 기초

5-1 용어

5-2 연관관계가 필요한 이유


@Entity
public class Member {

    private Long id;

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

    @Column(name = "TEAM_ID")
    private Long teamId;
}

@Entity
public class Team {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
}
//조회
Member findMember = em.find(Member.class, member.getId());
//연관관계가 없음
Team findTeam = em.find(Team.class, team.getId());

5-3 단방향 연관관계


@Entity
public class Member {

    private Long id;

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

    private int age;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
}
public class MainJPA {
    public static void main(String[] args) {
        //팀 저장
        Team team = new Team("TeamA");
        em.persist(team);

        //회원 저장
        Member member = new Member("member1", team); //단방향 연관관계 설정, 참조 저장
        em.persist(member);

        //조회
        Member findMember = em.find(Member.class, member.getId());

        //참조를 사용해서 연관관계 조회
        Team findTeam = findMember.getTeam();

        // 새로운 팀B
        Team teamB = new Team("TeamB");
        em.persist(teamB);

        // 회원1에 새로운 팀B 설정
        member.setTeam(teamB);
    }
}

5-4 양방향 연관관계


@Entity
public class Member {

    private Long id;

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

    private int age;

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

@Entity
public class Team {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "team")
    List<Member> members = new ArrayList<Member>();
}

5-5 연관관계의 주인과 mappedBy

@OneToMany(mappedBy = "team")

  • 객체 : 사실 2개의 단방향 연관관계
  • 테이블 : PK, FK를 통해 양방향 연관관계

1) 딜레마~!

Member 객체 자체와 테이블 매핑 vs Team 속 members 리스트를 통해 테이블 매핑

2) 연관관계의 주인(Owner)

위의 두 관계 중 하나만 연관관계 주인으로 설정

a. 주인

외래키가 있는 쪽이 주인!!!(team)

  • 1대n 관계에서 n 쪽
  • 외래키 관리(등록, 수정)
  • mappedBy 속성 사용X

b. 비 주인

주인의 반대편, PK 있는 쪽(members)

  • 1대n 관계에서 1 쪽
  • 수정 불가, 읽는 것만 가능
  • mappedBy 속성 사용!
  • @OneToMany(mappedBy = "team")

5-6 자주 하는 실수

1) 양방향 객체 설정 필수

class Main {
    public static void main(String[] args) {
        Team team = new Team("TeamA");
        em.persist(team);

        // 1. 역방향(주인이 아닌 방향)만 연관관계 설정
        Member member = new Member("member1");
        team.getMembers().add(member);
        em.persist(member);
        // 오류!!!

        // 2. 연관관계 주인 방향도 값 설정
        Member member = new Member("member1", team);//!!!!!!
        team.getMembers().add(member);
        em.persist(member);
        // 정상 작동!!!
    }
}

2) 연관관계 편의 메서드


@Entity
public class Member {
    //...

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

    public void changeTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);// !!!!
    }
}

3) 무한루프

toString(), lombok, JSON 생성 라이브러리

a. toString()

b. 이외