beadss / jpa-study

jpa슽터디입니다
1 stars 2 forks source link

8장 정리 완료 #21

Open 2xel opened 5 years ago

2xel commented 5 years ago

8. 프록시와 연관관계 관리

1. 프록시

// 회원 엔티티
@Entity
public class Member {
    private String username;

    @ManyToOne
    private Team team;

    public Team getTeam() {
        return tream;
    }

    @public String getUsername() {
        return username;
    }
    ...
}

//팀 엔티티
@Entity
public class Team {
    private String name;

    public String getName() {
        return name;
    }
    ...
}

// 회원과 팀 정보를 출력하는 비즈니스 로직
public void printUserAndTeam(String memberId) {
    Member member = em.find(Member.class, memberId);
    Team team = member.getTeam();
    System.out.println("회원 이름:" + member.getUsername());
    System.out.println("소속팀: " + team.gretName());
}

// 회원 정보만 출력하는 비즈니스 로직
public String printUser(String memberId) {
    Member member = em.find(Member.class, memberId);
    System.out.println("회원 이름:" + member.getUsername());
}

프록시랑 지연로딩에 대해 설명

1.1 프록시 기초

프록시의 특징

프록시 객체의 초기화

프록시의 특징

1.2 프록시와 식별자(잘 이해가 가지 않음)

Member member = em.find(Member.class, "member1");
Team team = em.getReference(Team.class, "team1");
member.setTeam(team);

1.3 프록시 확인

boolean isLoad = em.getEntityManagerFactory()
                    .getPersistenceUnitUtil().isLoaded(entity);
System.out.println("isLoad = " + isLoad);

2. 즉시 로딩과 지연 로딩

2.1 즉시 로딩

// 즉시로딩 설정
@Entity
public class Member {
    ...
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    ...
}

// 즉시로딩 실행 코드
Member member = em.find(Member.class, "member1");
Team team = member.getTeam();   // 객체 그래프 탐색
SELECT
    M.MEMBER_ID AS MEMBER_ID,
    M.TEAM_ID AS TEAM_ID,
    M.USERNAME AS USERNAME,
    T.TEAM_ID AS TEAM_ID,
    T.NAME AS NAME
FROM
    MEMBER M LEFT OUTTER JOIN TEAM T
        ON M.TEAM_ID=T.TEAM_ID
WHERE
    M.MEMBER_ID='member1'

(참고)NULL 제약조건과 JPA 조인전략

2.2 지연 로딩

// 지연로딩 설정
@Entity
public class Member {
    ...
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
}

// 지연 로딩 실행 코드
Member member = em.find(Member.class, "member1");
Team team = member.getTeam()l   // 객체 그래프 탐색
team.getName(); // 팀 객체 실제 사용
-- em.find(Member.class, "member1") 호출시
SELECT * FROM MEMBER
WHERE MEMBER_ID = "member1"

-- team.getName() 호출로 프록시 객체가 초기화 되면
SELECT * FROM TEAM
WHERE TEAM_ID = "team1"

2.3 즉시 로딩, 지연 로딩 정리

3. 지연 로딩 활용

3.1 프록시와 컬렉션 래퍼

3.2 JPA 기본패치 전략

3.3 컬렉션에서 FetchType.EAGER 사용 시 주의점

4. 영속성 전이: CASCADE

// 부모 엔티티
@Entity
public class Parent {
    @Id @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "parent")
    private List<Child> children = new ArrayList<>();
    ...
}

// 자식 엔티티
@Entity
public class Child {
    @Id @GeneratedValue
    private Long id;

    @ManyToOne
    private Parent parent;
    ...
}

// 부모 자식 저장
private static void saveNoCascade(EntityManager em) {
    // 부모 저장
    Parent parent = new Parent();
    em.persist(parent);

    // 1번 자식 저장
    Child child1 = new Child();
    child1.setParent(parent);
    parent.getChildren().add(child1);
    em.persist(child1);

    // 2번 자식 저장
    Child child2 = new Child();
    child2.setParent(parent);
    parent.getChildren().add(child2);
    em.persist(child2);
}

4.1 영속성 전이: 저장

// CASCADE 옵션 적용
@Entity
public class Parent {
    ...
    @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
    private List<Child> children = new ArrayList<>();
    ...
}

// CASCADE 저장 코드
private static void saveWithCascade(EntityManager em) {
    Child child1 = new Child();
    Child child2 = new Child();

    Parent parent = new Parent();
    child1.setParent(parent);
    child2.setParent(parent);
    parent.getChildren().add(child1);
    parent.getChildren().add(child2);

    em.persist(parent);
}

4.2 영속성 전이: 삭제

Parent findParent = em.find(Parent.class, 1L);
Child findChild1 = em.find(Child.class, 1L);
Child findChild2 = em.find(Child.class, 2L);

em.remove(findChild1);
em.remove(findChild2);
em.remove(findParent);
Parent findParent = em.find(Parent.class, 1L);
em.remove(findParent);

4.3 CASCADE의 종류

// CascadeType 코드
public enum CascadeType {
    ALL,        // 모두
    PERSIST,    // 영속
    MERGE,      // 병합
    REMOVE,     // 삭제
    REFRESH,    // REFRESH
    DETACH      // DETACH
}

5. 고아 객체

// 고아 객체 제거 기능 설정
@Entity
public class Parent {
    @Id @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "parent", orphanRemoval = true)
    private List<Child> children = new ArrayList<>();
    ...
}

// 사용 코드
Parent parent1 = em.find(Parent.class, id);
parent1.getChildren().remove(0);    // 첫번째 자식 엔티티를 컬렉션에서 제거
DELETE FROM CHILD WHERE ID=?

8.6 영속성 전이 + 고아 객체, 생명주기

// 자식을 저장하려면 부모에 등록하면 된다.
Parent parent = em.find(Parent.class, parentId);
parent.addChild(child1);

// 자식을 삭제하려면 부모에서 제거
Parent parent = em.find(Parent.class, parentId);
parent.getChildren().remove(removeObject);
joont92 commented 5 years ago

ㄷㄷㄷ

beadss commented 5 years ago

@joont92 어떤 부분에서 ㄷㄷㄷ임?