Какую аннотацию я должен использовать: @IdClass или @EmbeddedId



The JPA (Java Persistence API) спецификация имеет 2 различных способа указать составные ключи сущности:@IdClass и @EmbeddedId.



Я использую обе аннотации на моих отображенных объектах, но это оказывается большой беспорядок для людей, которые не очень знакомы с JPA.



Я хочу принять только один способ определить составные ключи. Какой из них действительно лучший? Зачем?

855   7  

7 ответов:

Я считаю, что @EmbeddedId вероятно, более подробно, потому что с @IdClass вы не можете получить доступ ко всему объекту первичного ключа с помощью любого оператора доступа к полю. Используя @EmbeddedId можно сделать так:

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

это дает четкое представление о полях, которые составляют составной ключ, потому что все они агрегируются в классе, доступ к которому осуществляется через оператор доступа к полю.

еще одна разница с @IdClass и @EmbeddedId это когда дело доходит до написания HQL :

С @IdClass вы пишете:

select e.name from Employee e

и @EmbeddedId вы должны написать:

select e.employeeId.name from Employee e

вы должны написать больше текста для того же запроса. Некоторые могут возразить, что это отличается от более естественного языка, как тот, который продвигается IdClass. Но в большинстве случаев понимание прямо из запроса, что данное поле является частью составного ключа, имеет неоценимую помощь.

Я обнаружил экземпляр, где мне пришлось использовать EmbeddedId вместо IdClass. В этом случае существует объединенная таблица, в которой определены дополнительные столбцы. Я попытался решить эту проблему с помощью IdClass для представления ключа сущности, которая явно представляет строки в таблице соединения. Я не мог заставить его работать таким образом. К счастью, "Java Persistence With Hibernate" имеет раздел, посвященный этой теме. Одно из предложенных решений было очень похоже на мое, но вместо этого он использовал EmbeddedId. Я моделируется мои объекты после тех, в книге он теперь ведет себя правильно.

существует три стратегии использования составного первичного ключа:

  • пометить как @Embeddable и добавьте к своему классу сущностей нормальное свойство для него, отмеченное @Id.
  • добавьте в свой класс сущностей обычное свойство для него, отмеченное @EmbeddedId.
  • добавьте свойства в свой класс сущностей для всех его полей, отметьте их @Id, и отметьте свой класс сущности с @IdClass, поставляя класс вашего первичного ключа класс.

использование @Id С классом, помеченным как @Embeddable Это самый естественный подход. Элемент @Embeddable тег может быть использован для не первичного ключа встраиваемых значений в любом случае. Это позволяет рассматривать составной первичный ключ как одно свойство, и это позволяет повторно использовать @Embeddable класса в других таблицах.

следующим наиболее естественным подходом является использование @EmbeddedId тег. Здесь класс первичного ключа не может использоваться в других таблицах, так как он не является @Embeddable сущность, но она позволяет нам рассматривать ключ как один атрибут некоторого класса.

наконец, использование @IdClass и @Id аннотации позволяют сопоставить составной класс первичного ключа, используя свойства самой сущности, соответствующие именам свойств в классе первичного ключа. Имена должны соответствовать (нет механизма для переопределения этого), и класс первичного ключа должен выполнять те же обязательства, что и с двумя другими методами. Единственный преимуществом такого подхода является его способность "скрывать" использование класса первичного ключа от интерфейса заключающей сущности. Элемент @IdClass аннотация принимает параметр значения типа класса, который должен быть классом, используемым в качестве составного первичного ключа. Поля, соответствующие свойствам используемого класса первичного ключа, должны быть аннотированы с помощью @Id.

ссылка:http://www.apress.com/us/book/9781430228509

насколько я знаю, если ваш композитный ПК содержит FK, его проще и проще использовать @IdClass

С @EmbeddedId вы должны определить отображение для вашего столбца FK дважды, onece в @Embeddedable и раз для как т. е. @ManyToOne здесь @ManyToOne должен быть только для чтения(@PrimaryKeyJoinColumn), потому что вы не можете иметь один столбец из двух переменных (возможные конфликты).
Таким образом, вы должны установить свой FK с помощью простого типа в @Embeddedable.

на другом сайте с помощью @IdClass этот ситуация может быть обработана гораздо проще, как показано в первичные ключи через Onetoone и ManyToOne отношения:

пример 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 class

...
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;
    }
}

Я думаю, что главное преимущество заключается в том, что мы могли бы использовать @GeneratedValue для идентификатора при использовании @IdClass? Я уверен, что мы не можем использовать @GeneratedValue на @EmbeddedId.

составной ключ не должен иметь @Id собственность, когда есть.

С EmbeddedId вы можете использовать предложение IN в HQL, например:FROM Entity WHERE id IN :ids где id является EmbeddedId тогда как это боль, чтобы достичь того же результата с IdClass вы хотите сделать что-то вроде FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN

Comments

    Ничего не найдено.