[JPA] 복합키 - 비식별관계 매핑하기 (@IdClass, @EmbeddedId)

반응형
728x90
반응형

테이블 구조

부모테이블 자식테이블 식별자 클래스
ParentA.java ChildA.java ParentAId.java
ParentB.java ChildB.java ParentBId.java

 

 

@IdClass

1) ParentA.java

package com.book.jpa.chapter07.identifying.idClass;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;

@Entity
@IdClass(ParentAId.class)
public class ParentA {
    @Id
    @Column(name = "PARENT_ID1")
    private String id1; // ParentAId 의 id1 과 연결

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

    private String name; // ParentAId 의 id2 와 연결
}

 

테이블 생성 쿼리
create table parenta (
        parent_id1 varchar(255) not null,
        parent_id2 varchar(255) not null,
        name varchar(255),
        primary key (parent_id1, parent_id2)
    )

 

 

2) ChildA.java

package com.book.jpa.chapter07.identifying.idClass;

import javax.persistence.*;

@Entity
public class ChildA {
    @Id
    private String id;

    @ManyToOne
    @JoinColumns({ // name , referencedColumnName 가 같을땐 referencedColumnName 생략 가능
            @JoinColumn(name = "PARENT_ID1", referencedColumnName = "PARENT_ID1"),
            @JoinColumn(name = "PARENT_ID2", referencedColumnName = "PARENT_ID2")
    })
    private ParentA parentA;
}

 

테이블 생성 쿼리
create table childa (
        id varchar(255) not null,
        parent_id1 varchar(255),
        parent_id2 varchar(255),
        primary key (id)
    )

 

 

3) ParentAId.java

package com.book.jpa.chapter07.identifying.idClass;

import lombok.EqualsAndHashCode;

import java.io.Serializable;

@EqualsAndHashCode
public class ParentAId implements Serializable {
    private String id1;
    private String id2;

    public ParentAId() {

    }

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

 

 

 

@EmbeddedId

1) ParentB.java

package com.book.jpa.chapter07.identifying.embeddedId;

import javax.persistence.*;

@Entity
public class ParentB {
    @EmbeddedId
    private ParentBId id;

    private String name; // ParentAId 의 id2 와 연결
}

 

테이블 생성 쿼리
create table parentb (
        parent_id1 varchar(255) not null,
        parent_id2 varchar(255) not null,
        name varchar(255),
        primary key (parent_id1, parent_id2)
    )

 

 

2) ChildB.java

package com.book.jpa.chapter07.identifying.embeddedId;

import javax.persistence.*;

@Entity
public class ChildB {
    @Id
    private String id;

    @ManyToOne
    @JoinColumns({ // name , referencedColumnName 가 같을땐 referencedColumnName 생략 가능
    	    // name : 자식 테이블의 컬럼명
            // referencedColumnName : 조인 대상 부모의 컬럼명 
            @JoinColumn(name = "PARENT_ID1", referencedColumnName = "PARENT_ID1"),
            @JoinColumn(name = "PARENT_ID2", referencedColumnName = "PARENT_ID2")
    })
    private ParentB parentB;
}

 

테이블 생성 쿼리
create table childb (
       id varchar(255) not null,
        parent_id1 varchar(255),
        parent_id2 varchar(255),
        primary key (id)
    )

 

 

3) ParentBId.java

package com.book.jpa.chapter07.identifying.embeddedId;

import lombok.EqualsAndHashCode;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import java.io.Serializable;

@Embeddable
// @EqualsAndHashCode
public class ParentBId implements Serializable {
    @Column(name = "PARENT_ID1")
    private String id1;

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

    public ParentBId() {

    }

    public ParentBId(String id1, String id2) {
        this.id1 = id1;
        this.id2 = id2;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ParentAId parentAId = (ParentAId) o;
        return Objects.equals(id1, parentAId.id1) && Objects.equals(id2, parentAId.id2);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id1, id2);
    }
}

 

 

 

@IdClass vs @EmbeddedId

  @IdClass @EmbeddedId
식별자 클래스 조건 - Serializable 구현해야한다.
- equals, hashCode 구현해야한다.
- 기본 생성자가 있어야한다.
- 식별자 클래스는 public 이여야 한다.
- @Embeddable 어노테이션을 붙여야한다.
- Serializable 구현해야한다.
- equals, hashCode 구현해야한다.
- 기본 생성자가 있어야한다.
- 식별자 클래스는 public 이여야 한다.
Entity set  ParentA parentA1 = new ParentA();
parentA1.setId1("myId1");
parentA1.setId2("myId2");
parentA1.setName("parentName");
ParentB parentB = new ParentB();
ParentBId parentId = new ParentBId("myId1", "myId2");
parentB.setId(parentId);
parentB.setName("parentName");

 

 

 

식별자 클래스에 equals, hashCode 재정의 필요한 이유

 ParentA parentA1 = new ParentA();
 parentA1.setId1("myId1");
 parentA1.setId2("myId2");
 parentA1.setName("parentName");
 
 
 ParentA parentA2 = new ParentA();
 parentA2.setId1("myId1");
 parentA2.setId2("myId2");
 parentA2.setName("parentName");
 
 System.out.println(parentA1 == parentA2) // true 가 나와야한다.

 

parentA1, parentA2 인스턴스는 equals 를 재정의하지 않으면, Object 의 equals()의 결과인 false 가 나온다. 하지만 parentA1, parentA2 는 JPA에서 식별키가 동일하므로 true가 나오도록 equals 를 재정의해줘야한다.

 

 

 

 

반응형

Designed by JB FACTORY