시그마 삽질==six 시그마

JPA -고급 매핑 본문

프로그래밍/JPA

JPA -고급 매핑

Ethan Matthew Hunt 2020. 4. 9. 20:55
우아한 형제들의 김영한 팀장님의  '자바 ORM 표준 JPA 프로그래밍'을

구입하시길 강력 추천드립니다.

책 구입을 원하시는분은 요기를 클릭하시면 됩니다.

저자 직강 인프런 강의도 있습니다 궁금하신분은 요기를 클릭

하단의 내용은 제가 예전에 읽었던 내용을 요약 정리한 것입니다.

 

1.상속관계 매핑

 

객체지향에서의 상속 그러나 DB는 상속이란 개념없음. 대신 슈퍼타입 서브타입관계만 있을뿐 두관계 맵핑이 상속관계매핑임

 

자바

부모: layout

자식: official,notice,global,news

 

1)각각의 테이블로 변환

 

조인전략(부모의 기본키를 자식이 받아서 기본키+외래키로 사용함-식별관계)

(정규화 but 조인으로 성능저하,insert2번)

@Inheritance(strategy=InheritanceType.JOINED)

 

테이블

부모: layout

자식: official,notice,global,news

 

2)통합 테이블로 변환

 

단일테이블 전략(조인x빠름, but 동일x컬럼은 null허용,점점커져서 느려질수도)

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

 

테이블

부모: layout 테이블에 dType 이라고 컬럼하나 두고 (official,notice,global,news)

 

 

 

3) 서브타입테이블로 변환<--최악

 

테이블 :official,notice,global,news 요기에 layout 컬럼들도 포함되 있음

 

구현 클래스별 테이블 전략(각자도생,묶어서 쿼리힘듬,여러 자식테이블 함께 조회시 성능 느림union해야함)

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

 

4)@MappedSuperClass

 

1~3은 전부 다 @Entity로 구현해야함.

But 위와같은 상속관계 매핑은 아니지만 부모 클래스는 테이블과는 매핑없이

자식클래스에게 매핑정보만 제공하고 싶을땐 위 어노테이션 사용하면됨

추상클래스로 만들어라

 

 

2. 복합키와 식별관계 매핑

 

1)비식별관계<-----------------대세!!!!!

 

부모의 기본키 받아 자식테이블의 외래키로만 사용

 

(1) 필수적 식별관계(Mandatory): FK에 null 허용x, 연관관계 필수임(내부조인만 사용)<---추천

(2) 선택적 비식별관계(Optional): FK에 null 허용, 연관관계 선택가능 (외부조인사용,성능떨어짐)

(3) 부모 복합키 ,비식별관계 @IdClass(관계형DB) , @EmbeddedID(객체지향방법)

 

 

2)식별관계<---비추

 

부모의 기본키를 자식 테이블의 기본키+외래키로 사용

비추.. 기본키 자식테이블로 전파시 기본키 컬럼이 점점늘어남

복합키는 equals() hashCode() 구현 필수

 

 

 

 

 

 

****경우의 수****

 

 

 

 

1. 부모가 복합키

 

 1) 1:1

   (1)식별

   (2)비식별

 

2) 1:다

   (1)식별

   (2)비식별

 

 

 

 

@IdClass

관계형 DB 적 방법

Parent 엔티티에서(@IdClass로 식별자 클래스 ParentId 명시)+복합키 id를   각각 컬럼과 매핑해서 필드로 명시

식별자 클래스 ParentId에선  복합키id 각각 필드로 명시

 

@EmbeddedId

객체지향적임

Parent 엔티티에서 ParentId 클래스를 필드로 사용(@EmbeddedId)

식별자클래스에서(@Embeddable) 각 복합키 id 컬럼과 매핑

 

 

 

       가) @IdClass

 

-식별자 클래스 조건

식별자 클래스의 속성명과 엔티티 사용하는 식별자 속성명 같아야함

serializable 인터페이스 구현해야함

equals ,hashCode 구현

기본생성자 구현

식별자 클래스는 public 이어야함

@Entity
@IdClass(ParentId.class)
public class Parent {
    
    @Id
    @Column(name = "parent_id1")
    private String id1; //ParentId.id1과 연결

    @Id
    @Column(name = "parent_id2")
    private String id2; //ParentId.id2과 연결

    private String name;

}


@Entity
public class Child {

    @Id
    private String id;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "PARENT_ID1", referencedColumnName = "PARENT_ID1"),
            @JoinColumn(name = "PARENT_ID2", referencedColumnName = "PARENT_ID2")
    })
    private Parent parent;
}



public class ParentId implements Serializable {

    private String id1; //parent.id1 매핑
    private String id2; //parent.id2 매핑

    //equals,hash,기본생성
}




        Parent parent = new Parent();
        parent.setId1("myId1");
        parent.setId2("myId2");
        parent.setName("parentName");
        em.persist(parent);   //이렇게하면 알아서 식별자 클래스 ParentId 생성해서 연속성 컨텍스트의 키로 사용함.

       나) @EmbeddedId

 

-식별자 클래스 조건

@Embeddable 어노테이션 붙이기

serializable 인터페이스 구현해야함

equals ,hashCode 구현

기본생성자 구현

식별자 클래스는 public 이어야함

@Entity
public class Parent implements Serializable {
    
    @EmbeddedId
    private ParentId id;
    private String name;

}

@Entity
public class Child {

    @Id
    private String id;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "PARENT_ID1", referencedColumnName = "PARENT_ID1"),
            @JoinColumn(name = "PARENT_ID2", referencedColumnName = "PARENT_ID2")
    })
    private Parent parent;
}


@Embeddable
public class ParentId implements Serializable {



    @Column(name = "PARENT_ID1")
    private String id1; //ParentId.id1과 연결


    @Column(name = "PARENT_ID2")
    private String id2; //ParentId.id2과 연결

    
    //equals,hash,기본생성자
}



        Parent parent = new Parent();
        ParentId parentId = new ParentId("myId1","myId2");
        parent.setId(parentId);
        parent.setName("parentName");
        em.persist(parent);

 

 

 

 

2 부모가 복합키 x

 

 

 1) 1:1

   (1)식별

 

   (2)비식별

@Entity @Data
public class Board {
    @Id @GeneratedValue
    @Column(name = "BOARD_ID")
    private Long id;

    private String title;

    @OneToOne(mappedBy = "board")
    private BoardDetail boardDetail;

}


@Entity @Data
public class BoardDetail {
    @Id
    private Long boardId;

    @MapsId //BoardDetail.boardId 매핑
    @OneToOne
    @JoinColumn(name = "BOARD_ID")
    private Board board;
    private String content;


}


    public void save(){
        Board board= new Board();
        board.setTitle("제목");
        em.persist(board);

        BoardDetail boardDetail = new BoardDetail();
        boardDetail.setContent("내용");
        boardDetail.setBoard(board);
        em.persist(boardDetail);
    }

 

2) 1:다

   (1)식별

 

       가) @IdClass

@Entity
public class Parent {

    @Id
    @Column(name = "PARENT_ID")
    private String id;
    private String name;
    //...
}


@Entity
@IdClass(ChildId.class)
public class Child {

    @Id
    @ManyToOne
    @JoinColumn(name="PARENT_ID")
    public Parent parent;

    @Id
    @Column(name = "CHILD_ID")
    private String childId;

    private String name;
    //...

}

public class ChildId implements Serializable {

    private String parent; //Child.parent 매핑
    private String childId; //Child.childId 매핑

    //equals,hash,기본생성자

}



@Entity
@IdClass(GrandChildId.class)
public class GrandChild {

    @Id
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "PARENT_ID"),
            @JoinColumn(name = "CHILD_ID"),
    })
    private  Child child;

    @Id
    @Column(name = "GRANDCHILD_ID")
    private String id;

    private String name;
}


public class GrandChildId implements Serializable {
    private ChildId childId; //GrandChild.child 매핑
    private String id; //GrandChild.id 매핑

    //equals,hash,기본생성자


}

       나) @EmbeddedId

 

@MapsId 는 외래키와 매핑한 연관관계를 기본키에도 매핑하겠다는 뜻이다. @MapsId의 속성 값은 @EmbeddedId를 사용한 식별자 클래스의 기본 키 필드를 지정하면됨. 요기선 ChildId의 parentId 필드를 선택함

@Entity
public class Parent {

    @Id
    @Column(name = "PARENT_ID")
    private String id;
    private String name;
    //...
}


@Entity
public class Child {

    @EmbeddedId
    private ChildId id;

    @MapsId("parentId") //ChildId.parentId 매핑
    @ManyToOne
    @JoinColumn(name="PARENT_ID")
    public Parent parent;

    private String name;
    //...

}


@Embeddable
public class ChildId implements Serializable {

    private String parentId; //@MapsId("parentId")로 매핑

    @Column(name = "CHILD_ID")
    private String id;

    //equals,hash,기본생성자
}


@Entity
public class GrandChild {

    @EmbeddedId
    private GrandChildId id;

    @MapsId("childId") //GrandChildId.childId 매
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "PARENT_ID"),
            @JoinColumn(name = "CHILD_ID"),
    })
    private Child child;

    private String name;
    //...
}


@Embeddable
public class GrandChildId implements Serializable {

    private ChildId childId; //@MapsId("childId")로 매핑

    @Column(name = "GRANDCHILD_ID")
    private String id;
    //equals,hash,기본생성자
}

 

   (2)비식별

 

@Entity
public class Parent {

    @Id
    @GeneratedValue
    @Column(name = "PARENT_ID")
    private Long id;
    private String name;
    //...
}


@Entity
public class Child {
    @Id @GeneratedValue
    @Column(name = "CHILD_ID")
    private Long id;
    private String name;

    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;
    //...
}



@Entity
public class GrandChild {

    @Id @GeneratedValue
    @Column(name = "GRANDCHILD_ID")
    private Long id;
    private String name;

    @ManyToOne
    @JoinColumn(name = "CHILD_ID")
    private Child child;

}

 

 

 

3. 조인테이블

 

DB 연관관계 설정방법은 조인컬럼사용하던가(FK로 조인) 조인 테이블(연결 테이블) 사용하는 방법이 있다. 

조인컬럼사용시 선택적 비식별관계에서 내부조인사용할시 오판가능

 

 

 

 

 

'프로그래밍 > JPA' 카테고리의 다른 글

JPA -값 타입  (0) 2020.04.09
JPA -프록시와 연관관계 관리  (0) 2020.04.09
JPA -다양한 연관관계 매핑  (0) 2020.04.09
JPA -연관관계 매핑  (1) 2020.04.08
JPA -Entity Mapping  (0) 2020.04.08
Comments