Разрешает ли спецификация JPA ссылки на столбцы без первичного ключа?

Разрешает ли спецификация JPA простые ссылки на столбцы без первичного ключа?

У меня есть простой столбец альтернативного / естественного ключа (UNIQUE, NOT NULL) iso_code в моей таблице стран, который я хотел бы использовать в качестве ссылки, но Dali в Eclipse показывает ошибку проверки, а Hibernate генерирует исключение MappingException.

Разрешен ли такой общий сценарий?

2 ответа

Решение

@axtavt: Похоже, что ваш ответ не был правильным. Я только что получил письмо от авторов "Pro JPA 2.0", которые также сами работали над спецификацией JPA.

"В вашем примере класс Zip имеет отношение к стране:

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

Похоже, что он пытается указать столбец внешнего ключа country_code на столбец iso_code в таблице Country, который не является PK. JPA никогда не позволяла вам создавать подобные отношения, потому что без указания PK страны не было бы способа однозначно определить, какой экземпляр Country находится в отношениях. Вы просто сталкиваетесь с проблемой, когда добираетесь до производной части идентификатора, но проблема, похоже, заключается в самих недопустимых отношениях ".

Таким образом, спецификация JPA вообще не разрешает отношения /FK для не-PK столбцов...

Поддержка отношений, которые ссылаются на столбцы не-PK, является необязательной функцией. В простых случаях он поддерживается Hibernate, но его нельзя использовать как часть идентификатора с использованием dervied.

Однако до тех пор, пока вы не получите идентификатор (т. Е. Если вы можете установить значение компонента первичного ключа вручную), вы можете попытаться поиграть с отображениями только для чтения, что-то вроде этого:

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

    @Id
    @Column(name = "country_code")
    private String countryCode; // Primary key component should be set manually

    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code", 
        insertable = false, updateable = false)
    private Country country = null; // Read-only relationship based on a value 
                                    // of primary key component

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