Почему это отображение 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"
- Почему это неправильно в синтаксисе JPA 2.0 (см. Аннотацию @Id в Zip.country)? Я не думаю, что это так. Ведь типы Zip.country и ZipId.country не могут быть одинаковыми для JPA 2 из-за аннотации @Id в @ManyToOne и PK, являющегося простым целым числом, которое становится аналогом класса ID. Кто-нибудь может проверить / подтвердить это, пожалуйста?
- Может ли это быть ошибкой, возможно, в 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 { ... }
Надеюсь, это поможет!