Почему это отображение JPA 2.0 дает мне ошибку в Eclipse/JBoss Tools?

У меня следующая ситуация: http://www.kawoolutions.com/media/zips-countries-geoareas.png

Отображения JPA 2.0 (возможно, будет достаточно рассмотреть только классы Zip и ZipId, так как именно отсюда и возникает ошибка):

@Entity
@Table(name = "GeoAreas")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
public abstract class GeoArea implements Serializable
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    protected Integer id;

    @Column(name = "name")
    protected String name;

    ...
}

@Entity
@Table(name = "Countries")
@DiscriminatorValue(value = "country")
public class Country extends GeoArea
{
    @Column(name = "iso_code")
    private String isoCode;

    @Column(name = "iso_nbr")
    private String isoNbr;

    @Column(name = "dial_code")
    private Integer dialCode = null;

    ...
}

@Entity
@Table(name = "Zips")
@IdClass(value = ZipId.class)
public class Zip implements Serializable
{
    @Id
    @Column(name = "code")
    private String code;

    @Id
    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code")
    private Country country = null;

    ...
}

public class ZipId implements Serializable
{
    private String country;

    private String code;

    ...
}

Довольно простой дизайн:

Страна является географической зоной и наследует идентификатор от корневого класса. Почтовый индекс является уникальным в своей стране, поэтому он сочетает в себе код ISO и фактический почтовый код в виде PK. Таким образом, Zips ссылается на Country.iso_code, на котором есть альтернативный уникальный, ненулевой ключ (ссылка на столбец без первичного ключа!). Ассоциация Zip.country получает аннотацию @Id, а имя ее переменной совпадает с именем в ее классе идентификаторов ZipId.

Однако я получаю это сообщение об ошибке из Eclipse (также используя JBoss Tools):

Сообщение проверки: "Атрибут, соответствующий стране атрибута класса идентификатора, не имеет правильный тип java.lang.String"

  1. Почему это неправильно в синтаксисе JPA 2.0 (см. Аннотацию @Id в Zip.country)? Я не думаю, что это так. Ведь типы Zip.country и ZipId.country не могут быть одинаковыми для JPA 2 из-за аннотации @Id в @ManyToOne и PK, являющегося простым целым числом, которое становится аналогом класса ID. Кто-нибудь может проверить / подтвердить это, пожалуйста?
  2. Может ли это быть ошибкой, возможно, в JBoss Tools? (Какой программный компонент сообщает об вышеуказанной ошибке? При помещении трех таблиц и классов сущностей в новый проект JavaSE с точным кодом ошибки не отображается...)

3 ответа

Решение

Отвечая на собственный вопрос...

При моделировании ссылки я использую String, потому что FK указывает на столбец iso_code в таблице стран, которая является CHAR(2), так что в основном мое отображение верно. Однако проблема в том, что JPA 2.0 не допускает ничего, кроме ссылок на столбцы первичного ключа. Это то, что показывает валидатор Eclipse Dali JPA.

Взято из "Pro JPA 2.0" Китом / Шинкариолом, с.283, вверху, "Основные правила для производных идентификаторов" (правило № 6): "Если атрибут id в объекте является отношением, то тип соответствующего атрибута в Класс id относится к тому же типу, что и тип первичного ключа целевой сущности в отношении (независимо от того, является ли тип первичного ключа простым типом, классом идентификатора или встроенным классом идентификатора). "

Личное приложение:

Я не согласен с JPA 2.0, имеющим это ограничение. Отображения JPA 1.0 позволяют ссылаться на столбцы не-PK. Обратите внимание, что вместо этого я использую сопоставления JPA 1.0. Я бы скорее интересовался причиной, по которой это ограничение было наложено на JPA 2.0. JPA 2.0 определенно ограничивает.

Я бы сказал, сфокусируйте ваше внимание на отношениях CompoundIdentity. См. Этот вопрос и мой ответ там. Помогите сопоставить составной внешний ключ в JPA 2.0.

ZipId не имеет поля "страна" в вашем случае

Я не проверял ваш код, но он выглядит в значительной степени связанным с использованием аннотации @PrimareKeyJoinColumn.

Спецификация JPA 2.0 в разделе 11.1.40 гласит:

Аннотация PrimaryKeyJoinColumn используется для соединения первичной таблицы подкласса сущности в стратегии отображения JOINED с первичной таблицей ее суперкласса; он используется в аннотации SecondaryTable для соединения вторичной таблицы с первичной таблицей; и он может использоваться в отображении OneToOne, в котором первичный ключ ссылающегося объекта используется в качестве внешнего ключа для ссылочного объекта [108].

Пример в спецификации выглядит как ваш случай.

@Entity
@Table(name="CUST")
@Inheritance(strategy=JOINED)
@DiscriminatorValue("CUST")
public class Customer { ... }

@Entity
@Table(name="VCUST")
@DiscriminatorValue("VCUST")
@PrimaryKeyJoinColumn(name="CUST_ID")
public class ValuedCustomer extends Customer { ... }

Надеюсь, это поможет!

Другие вопросы по тегам