티스토리 뷰

JPA

JPA 에서의 식별과 비식별

절취선 2022. 5. 12. 00:20
반응형

JPA 에서의 식별과 비식별

DB 테이블 관계는 외래키 포함 여부에 따라 식별비식별로 구분한다.

  1. 식별 관계
    • 부모 테이블의 기본키를 받아 자식 테이블이 기본키 + 외래키로 사용하는 관계

  1. 비식별 관계

    • 부모테이블의 기본키를 받아 자식 테이블이 외래키로만 사용하는 관계

    • 비식별은 또 다시 필수와 선택으로 나뉜다.

      • 필수적 비식별

        • 외래키에 NULL을 허용하지 않는다. 필수적 연관관계를 가진다.
      • 선택적 비식별

        • 외래키에 NULL을 허용한다. 연관관계를 선택적으로 선택한다.

식별 비식별 장단점

  • 식별 관계의 장점

    • 데이터의 정합성 유지를 DB에서 한번 더 할 수 있다
    • 자식 테이블에 데이터가 존재한다면 부모 데이터도 반드시 존재한다고 보장할 수 있다
  • 식별 관계의 단점

    • 요구사항이 변경되었을 경우 구조 변경이 어렵다
    • 자식 객체로 넘어갈 수록 저장해야 하는 기본 키 인덱스의 수가 증가한다.
    • 부모 키를 자식 테이블이 기본키로 사용되면서 테이블 구조가 유연하지 못하다.
  • 비식별 관계의 장점

    • 변경되는 요구사항을 유동적으로 수용할 수 있다
    • 부모 데이터와 독립적인 자식 데이터를 생성할 수 있다
  • 비식별 관계의 단점

    • 데이터 정합성을 지키기 위해서는 별도의 비즈니스 로직이 필요하다.
    • 자식 데이터가 존재해도 부모 데이터가 존재하지 않을 수 있다
    • 즉, 데이터 무결성을 보장하지 않는다

복합키 비식별 관계 매핑 방식

식별자 필드가 하나일 때는 보통 자바의 기본 타입을 사용하므로 문제가 없지만 식별자 필드가 2개 이상이라면 별도의 식별자 클래스를 만들어 사용해야한다.

식별자 클래스를 사용하는 이유는 컨텍스트가 엔티티를 관리하는 과정에서 식별자를 키로 사용하는데
복합키를 가지는 테이블에서 식별자를 구분하기 위해서는 equlashashCode 메소드를 사용해야하기 때문이다.

@IdClass

이 방식은 데이터 베이스 관점에 초첨이 맞춰져 있는 어노테이션이다.

식별자를 구분하기 위해 식별자 클래스를 별도로 만들어줘야하며 해당 어노테이션을 통해 식별자 클래스를 명시해 줄 수 있다.

  • 식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야한다.
  • Serializable 인터페이스 구현
  • equals, hashCode 메소드 구현
  • 기본 생성자가 있어야한다.
  • 식별자 클래스는 public 이어야한다.
@Entity
@IdClass(ParentId.class)
public class Parent{
    @Id
    @Column(name = "PARENT_ID1")
    private String id1;

    @Id
    @Column(name = "PARENT_ID2")
    private String id2;

    private String name;
}
public class ParentId implements Serializable{

    private String id1;

    private String id2;

    public ParentId(){}
    public ParentId(String id1, String id2){
        this.id1 = id1;
        this.id2=id2;
    }

    @Override
    public boolean equals(Object o){}

    @Override
    public boolean hashCode(){}
}

참조 방식또한 결국에 식별키를 비교하여 사용해야 하기 때문에 식별자 클래스를 통해 참조해야한다.

ParentId parentid = new ParentId("myid1", "myid2");
Parent parent = em.find(Parent.class, parentId);

또한 부모 테이블의 기본 키 컬럼이 복합 키이므로 자식 테이블의 외래 키도 복합 키 이다.
따라서 외래 키 매핑 시 여러 컬럼을 매필야하 하므로 @JoinColumns 어노테이션을 사용한다.

@Entity
@IdClass(ParentId.class)
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;
}

@EmbaddedId

객체 지향적인 방식으로 Parent 엔티티에서 식별자 클래스를 직접 사용하고 @EmbaddedId 어노테이션을 적어주면 된다.

  • @EmbaddedId 어노테이션을 붙여주어야한다.
  • Serializable 인터페이스 구현
  • equals, hashCode 메소드 구현
  • 기본 생성자가 있어야한다.
  • 식별자 클래스는 public 이어야한다.
@Entity
public class Parent{
    @EmbaddedId
    private Parent id;
    private String name;
}
@EmbaddedId
public class ParentId implements Serializable{
    @Id
    @Column(name = "PARENT_ID1")
    private String id1;

    @Id
    @Column(name = "PARENT_ID2")
    private String id2;

    public ParentId(){}

    public ParentId(String id1, String id2){
        this.id1 = id1;
        this.id2=id2;
    }

    @Override
    public boolean equals(Object o){}

    @Override
    public boolean hashCode(){}
}

참조 방식또한 결국에 식별키를 비교하여 사용해야 하기 때문에 식별자 클래스를 통해 참조해야한다.

ParentId parentid = new ParentId("myid1", "myid2");
Parent parent = em.find(Parent.class, parentId);
반응형

'JPA' 카테고리의 다른 글

프록시  (0) 2022.05.14
임베디드 타입, 엔티티 타입  (0) 2022.05.13
ORM에서의 객체 연관 매핑  (0) 2022.05.11
SQL Mapper vs ORM  (0) 2022.05.10
JPQL(Java Persistence Query Language)  (0) 2022.05.09
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함