[JPA] 복합 키 매핑하는 법

시나브로·2021년 5월 19일
1

JPA

목록 보기
8/12
post-thumbnail

1. 비식별 관계 매핑


  JPA는 영속성 컨텍스트에 엔티티를 보관 시, 식별자를 사용하고 이를 구분하기 위해 equals와 hashcode를 사용해 비교한다. 이때 식별자가 2개 이상이면 별도의 식별자 클래스를 만들고 그곳에 equals와 hashcode를 구현해야한다.
JPA는 2가지 방법을 제공하고 있다.

1.1 @IdClass

구현 예제

ex)

< 부모 class >

@Entity
@IdClass(ItemId.class)
public class Item {

    @Id
    private Long id1; //ItemId.id1과 연결
    
    @Id
    private Long id2; //ItemId.id2과 연결
...
public class ItemId implements Serializable {

    private Long id1; //Item.id1과 연결
    private Long id2; //Item.id2과 연결
...

@Override
public boolean equals(Object obj){...}

@Override
public int hashcode(){...}
...
  • 필수 조건
    • 식별자 클래스 속성명과 엔티티에서 사용하는 식별자의 속성명이 동일해야한다
    • Sericalizable 인터페이스를 구현해야한다
    • equals, hashcode를 구현해야한다
    • 기본 생성자가 있어야한다
    • 식별자 클래스는 public이어야 한다



구현 예제

ex)

< 자식 class >

@Entity
public class Album {

    @Id
    private Long id;
    
    @ManyToOne
    @JoinColumn({
            @JoinColumn(name = "id1",
            referencedColumnName = "id1"),
            @JoinColumn(name = "id2",
                    referencedColumnName = "id2")
    })
    private Item item;
...
  • @JoinColumn의 name과 referencedColumnName가 같다면 referencedColumnName는 생략 가능

1.2 @EmbeddedId

  • @IdClass가 데이터베이스에 맞춘 방식이면 이 방식은 좀 더 객체지향적이다.

구현 예제

ex)

< 부모 class >

@Entity
public class Item {

    @EmbeddedId
    private ItemId id; 
    
...
@Embeddable
public class ItemId implements Serializable {

	@Column
    private Long id1; 
    @Column
    private Long id2; 
...

@Override
public boolean equals(Object obj){...}

@Override
public int hashcode(){...}
...
  • 필수 조건
    • @Embeddable 어노테이션 필수
    • Sericalizable 인터페이스를 구현해야한다
    • equals, hashcode를 구현해야한다
    • 기본 생성자가 있어야한다
    • 식별자 클래스는 public이어야 한다




2. 식별 관계 매핑


  식별관계에서 자식 테이블은 부모 테이블의 기본 키를 포함해서 복합 키를 구성해야 하므로, @IdClass나 @EmbeddedId를 사용해 매핑해야한다.

1.1 @IdClass

구현 예제

ex)

< 부모 class >

@Entity
public class Parent {

    @Id
    @Column(name = "PARENT_ID")
    private Long id; 
    
...

< 자식 class >

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

    @Id
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;
    
    @Id
    @Column(name = "CHILD_ID")
    private Long childId;
...
public class ChildId implements Serializable {

    private Long parent; //Child.parent 연결
    private Long childId; //Child.childId 연결
...

@Override
public boolean equals(Object obj){...}

@Override
public int hashcode(){...}
...
  • 식별관계는 기본 키, 외래 키 같이 매핑해야한다. 따라서 @Id와 @ManyToOne을 함께 사용한다.




1.2 @EmbeddedId

  • @EmbeddedId가 사용될 때 @MapsId를 사용해야한다.

구현 예제

ex)

< 부모 class >

@Entity
public class Parent {

    @Id
    @Column(name = "PARENT_ID")
    private Long parentId; 
    
...

< 자식 class >

@Entity
public class Child {

    @MapsId("parentId")
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;
    
    @EmbeddedId
    private ChildId id;
...
public class ChildId implements Serializable {

    private Long parentId; //@MapsId("parentId") 연결
    
    @Column(name = "CHILD_ID")
    private Long Id; 
...

@Override
public boolean equals(Object obj){...}

@Override
public int hashcode(){...}
...
  • @MapsId : 외래 키와 매핑한 연관관계를 기본 키에도 매핑하겠다는 의미





3. 일대일 식별 관계


  일대일 식별 관계는 자식 테이블의 기본 키 값으로 부모 테이블의 기본 키 값만 사용한다.

구현 예제

ex)

< 부모 class >

@Entity
public class Parent {

    @Id
    @Column(name = "PARENT_ID")
    private Long id; 
    
...

< 자식 class >

@Entity
public class Child {

    @MpasId
    @OneToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;
    
    @Id
    @Column(name = "CHILD_ID")
    private Long childId;
...
  • 식별자가 단순 컬럼 하나면 @MapsId를 사용하면 된다.
  • @MapsId@Id와 매핑된다.













참고 도서
profile
Be More!

0개의 댓글