Ошибка Eclipse при сопоставлении с @EmbeddedId

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

@Embeddable
public class DitaAdminAccountSkillPK implements Serializable {

  @ManyToOne
  @JoinColumn(name = "admin_id")
  private DitaAdmin admin;

  @ManyToOne
  @JoinColumn(name = "account_id")
  private DitaAccount account;

  //constructor, getters, setters...
}

И объект, который его использует:

@Entity
public class DitaAdminAccountSkill {

  @EmbeddedId
  private DitaAdminAccountSkillPK id;

  //constructor, getters, setters...
}

Теперь я хочу сопоставить объект в другом объекте следующим образом:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "id.admin")
private List<DitaAdminAccountSkill> accountSkills;

Обратите внимание на mappedBy = "id.admin" , который ссылается на поле admin в DitaAdminAccountSkillPK, используя id поле DitaAdminAccountSkill.

Это компилируется и работает отлично. Однако в eclipse появляется сообщение об ошибке: В атрибуте "accountSkills" значение "сопоставлено" значением "id.admin" не может быть разрешено для атрибута на целевой сущности.

Обратите внимание, что это проблема JPA, означающая, что фасет JPA жалуется. Теперь, я знаю, что я мог бы использовать @IdClass, но мне просто интересно, почему он думает об ошибке. Или, может быть, я делаю что-то ужасно неправильно?

Спасибо за указатели, Zbynek

Ответ 1

В соответствии с разделом 11.1.15 спецификации JPA 2.0: сопоставления отношений, определенные во встроенном классе id, не поддерживаются. Однако этот может быть, поддерживаемый используемой версией JPA, даже если он официально не поддерживается самим стандартом.

Если это так, вы можете отключить проверку для этого в Eclipse под Window -> Preferences -> Java Persistence -> JPA -> Errors/Warnings -> Attributes -> Cannot resolve attribute name.

Ответ 2

В моем случае проблема не была решена, пока я не установил следующее значение Ignore:

Project Facets > JPA > Errors/Warnings > Type > Mapped Java Class is a member class

Ответ 3

Прежде чем пытаться выполнить какие-либо предыдущие решения, сначала проверьте persistence.xml и убедитесь, что для параметра exclude-unlisted-classes установлено значение true или что все ваши сопоставленные классы перечислены в вашем persistence-unit.

Ответ 4

Думаю, что я опубликую решение, которое я нашел, которое соответствует спецификации JPA 2.0 и, похоже, работает одинаково.

Во-первых, спецификацию JPA 2.0 можно найти здесь: JSR-000317 Спецификация сохранения для Eval 2.0 Eval. Соответствующий раздел будет 2.4.1 "Первичные ключи, соответствующие производным тождествам"

Вот пример использования указанных вами классов:

Встроенный класс идентификаторов:

@Embeddable
public class DitaAdminAccountSkillPK implements Serializable {

    //No further annotations are needed for the properties in the embedded Id.

    //Needs to match the type of the id of your DitaAdmin object. I added 'Id' to the end of the property name to be more explicit.
    //Making the assumption here that DitaAdmin has a simple Integer primary key.
    private Integer adminId;

    //Needs to match the type of the id of your DitaAccount object. I added 'Id' to the end of the property name to be more explicit.
    //Making the assumption here that DitaAccount has a simple Integer primary key.
    private Integer accountId;


    //I'm adding a third property to the primary key as an example
    private String accountName;

    //constructor, getters, setters...

    //hashCode() and equals() overrides
}

"Зависимый" класс сущностей:

@Entity
public class DitaAdminAccountSkill {

    @EmbeddedId
    //Any overrides to simple Id properties should be handled with an attribute override
    @AttributeOverride(name = "accountName", column = @Column(name = "account_name"))
    private DitaAdminAccountSkillPK id;

    //MapsId refers to the name of the property in the embedded Id
    @MapsId("adminId")
    @JoinColumn(name="admin_id")
    @ManyToOne
    private DitaAdmin admin;

    @MapsId("accountId")
    @JoinColumn(name="account_id")
    @ManyToOne
    private DitaAccount account;

    //constructor, getters, setters...
}

"Родительский" класс сущностей:

public class DitaAdmin {

    @Id
    private Integer id;

    //...

    //Now your mappedBy attribute can refer to the admin object defined on DitaAdminAccountSkill which is also part of the Primary Key
    @OneToMany(fetch = FetchType.LAZY, mappedBy="admin")
    private List<DitaAdminAccountSkill> accountSkills;

    //...
}

Ответ 5

Настройки → Сохранение Java → JPA → Ошибки/Предупреждения → Атрибут → Встраиваемые классы идентификаторов не должны содержать сопоставлений отношений: (Игнорировать)