어떤 주석을 사용해야합니까 : @IdClass 또는 @EmbeddedId


128

JPA(자바 퍼시스턴스 API) 규격은 기업 복합 키를 지정하는 2 가지 방법이 있습니다 @IdClass@EmbeddedId.

매핑 된 엔터티에 두 주석을 모두 사용하고 있지만에 익숙하지 않은 사람들에게는 큰 혼란으로 판명되었습니다 JPA.

복합 키를 지정하는 한 가지 방법 만 채택하고 싶습니다. 어느 것이 정말 최고입니까? 왜?

답변:


86

필자 @EmbeddedId@IdClass필드 액세스 연산자를 사용하여 전체 기본 키 객체에 액세스 할 수 없기 때문에 더 자세한 정보 라고 생각합니다 . 를 사용하면 @EmbeddedId다음과 같이 할 수 있습니다.

@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
  @EmbeddedId EmployeeId employeeId;
  ...
}

이것은 필드 액세스 연산자를 통해 액세스되는 클래스에 모두 모이기 때문에 복합 키를 만드는 필드에 대한 명확한 개념을 제공합니다.

HQL을 작성할 때 와 다른 또 다른 차이점은 다음 @IdClass@EmbeddedId같습니다.

@IdClass당신 과 함께 쓰기 :

직원 e에서 e.name을 선택하십시오.

그리고 @EmbeddedId당신은 다음 과 같이 작성해야합니다 :

직원 e에서 e.employeeId.name을 선택하십시오.

동일한 쿼리에 대해 더 많은 텍스트를 작성해야합니다. 어떤 사람들은 이것이 이것에 의해 장려 된 것과 같은보다 자연스러운 언어와 다르다고 주장 할 수도 있습니다 IdClass. 그러나 대부분의 경우 주어진 필드가 복합 키의 일부라는 쿼리에서 이해하는 것은 매우 도움이됩니다.


10
나는 또한 같은위한 하나의 고유 한 사용 사례를 추가 할 것입니다 I 위에서 주어진 설명에 동의하지만 @IdClass내가 좋아하더라도 @EmbeddedId(대부분의 경우에있어 그가 제안 180cm 정도 안토니오 곤칼베스하여 세션에서이 알고 것은 우리가 사용할 수 있습니다 @IdClass경우 복합에 키 클래스에 액세스 할 수 없습니다 또는 우리가 그 시나리오 .IN 주석을 추가 할 수 없습니다 다른 모듈 또는 레거시 코드에서 오는 @IdClass우리에게 방법 우리 줄 것이다.
Gaurav Rawat

1
나는 그것이 사용하기위한 경우 것이 가능하다고 생각 @IdClass@Gaurav에 의해 지정된 주석이 바로 그 이유는 그 JPA 사양 목록을 모두 복합 키를 생성하는 방법 ... @IdClass그리고@EmbeddidId
kapad

20

복합 기본 키를 사용하는 세 가지 전략이 있습니다.

  • 로 표시하고로 @Embeddable표시된 일반 속성을 엔티티 클래스에 추가하십시오 @Id.
  • 로 표시된 일반 속성을 엔티티 클래스에 추가하십시오 @EmbeddedId.
  • 모든 필드에 대해 엔티티 클래스에 특성을 추가하고로 표시하고 @Id엔티티 @IdClass키를로 표시하여 기본 키 클래스의 클래스를 제공하십시오.

@Id로 표시된 클래스와 함께 사용하는 @Embeddable것이 가장 자연스러운 방법입니다. @Embeddable태그 어쨌든 기본 키가 아닌 임베드 값을 사용할 수 있습니다. 복합 기본 키를 단일 특성으로 취급하고 @Embeddable다른 테이블 에서 클래스를 재사용 할 수 있습니다.

다음으로 가장 자연스러운 방법은 @EmbeddedId태그를 사용하는 것입니다 . 여기서 기본 키 클래스는 @Embeddable엔티티 가 아니기 때문에 다른 테이블에서 사용할 수 없지만 키를 일부 클래스의 단일 속성으로 취급 할 수 있습니다.

마지막으로 @IdClassand @Id주석을 사용하면 기본 키 클래스의 속성 이름에 해당하는 엔터티 자체의 속성을 사용하여 복합 기본 키 클래스를 매핑 할 수 있습니다. 이름은 일치해야하며 (이를 재정의하는 메커니즘은 없습니다) 기본 키 클래스는 다른 두 기술과 동일한 의무를 준수해야합니다. 이 접근법의 유일한 장점은 엔 클로징 엔티티의 인터페이스에서 기본 키 클래스의 사용을 "숨기는"기능입니다. @IdClass주석은 클래스 화합물 일차 키로서 사용될 수 있어야 클래스 유형 값 파라미터를 취. 사용할 기본 키 클래스의 속성에 해당하는 필드에는 모두 주석이 달려 있어야합니다 @Id.

참조 : http://www.apress.com/us/book/9781430228509


17

IdClass 대신 EmbeddedId를 사용해야하는 인스턴스를 발견했습니다. 이 시나리오에는 추가 열이 정의 된 조인 테이블이 있습니다. 조인 테이블의 행을 명시 적으로 나타내는 엔터티의 키를 나타 내기 위해 IdClass를 사용 하여이 문제를 해결하려고했습니다. 나는 이런 식으로 작동하지 못했습니다. 고맙게도 "Hibernate에 대한 Java Persistence"에는이 주제에 대한 섹션이 있습니다. 제안 된 솔루션 중 하나는 내 것과 매우 유사하지만 대신 EmbeddedId를 사용했습니다. 나는 책에있는 것들이 이제 올바르게 동작하는 것을 따라 나의 물건들을 모델링했다.


13

복합 PK에 FK가 포함되어 있는지 아는 한 사용하기가 더 쉽고 간단합니다. @IdClass

으로 @EmbeddedId당신이 두 번 onece 당신의 FK 컬럼에 대한 매핑을 정의해야 @Embeddedable하고 일단 즉하는 한 @ManyToOne@ManyToOne읽기 전용 수 (가 @PrimaryKeyJoinColumn) 당신은 두 개의 변수 (가능한 충돌) 한 열 집합을 가질 수 있기 때문이다.
따라서 간단한 유형을 사용하여 FK를 설정해야합니다 @Embeddedable.

@IdClass이 상황을 사용하는 다른 사이트 에서는 OneToOne 및 ManyToOne Relationships를 통해 기본 키에 표시된 것처럼 훨씬 쉽게 처리 할 수 ​​있습니다 .

JPA 2.0 ManyToOne ID 주석 예

...
@Entity
@IdClass(PhonePK.class)
public class Phone {

    @Id
    private String type;

    @ManyToOne
    @Id
    @JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...
}

JPA 2.0 ID 클래스 예

...
public class PhonePK {
    private String type;
    private long owner;

    public PhonePK() {}

    public PhonePK(String type, long owner) {
        this.type = type;
        this.owner = owner;
    }

    public boolean equals(Object object) {
        if (object instanceof PhonePK) {
            PhonePK pk = (PhonePK)object;
            return type.equals(pk.type) && owner == pk.owner;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return type.hashCode() + owner;
    }
}

1
PK 클래스에 게터를 추가하는 것을 잊지 마십시오
Sonata

@Sonata 왜 게터가 필요한가요? 나는 getters / setters없이 그것을 시도하고 잘 작동합니다
xagaffar

id 클래스 예제에 감사드립니다! 결국 Serializable을 구현해야했습니다. 특히 IDE가 자동으로 생성 할 수있는 경우 게터 및 세터를 추가 할 수도 있습니다.
Starwarswii 2016 년

8

가장 큰 장점은 ?를 @GeneratedValue사용할 때 ID에 사용할 수 있다는 것 입니다 @IdClass. 에 사용할 수 없다고 확신 @GeneratedValue합니다 @EmbeddedId.


1
Embeddedid에서 @GeneratedValue를 사용할 수 없습니까?
Kayser

1
EmbeddedId와 함께 성공적으로 사용했지만 지원은 DB마다 다릅니다. 이것은 IdClass와 함께 사용하는 경우에도 마찬가지입니다. 스펙은 "GeneratedValue 어노테이션은 단순 (즉, 비 복합) 기본 키에만 이식 가능하게 사용될 수 있습니다"라고 말합니다.
BPS

4

복합 키를 사용할 @Id때는 속성 이 없어야합니다 @EmbeddedId.


1

EmbeddedId를 사용하면 예를 들어 HQL에서 IN 절을 사용할 수 있습니다. FROM Entity WHERE id IN :ids여기서 id는 EmbeddedId이지만 IdClass와 동일한 결과를 얻는 것은 고통 스럽습니다.FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.