Hibernate: где insertable = false, updatable = false принадлежит составным созвездиям первичных ключей с участием внешних ключей?
При реализации составных первичных ключей в Hibernate или других ORM существует до трех мест, где можно поставить insertable = false, updatable = false в составные созвездия первичных ключей, которые используют идентифицирующие отношения (FK, которые являются частью PK):
- В составной class PK «аннотация @Column (только classы @Embeddable) или
- В аннотацию ассоциации entity @ JoinColumn / s или
- В аннотацию @Column избыточного свойства PK classа сущности (только classы @IdClass)
Третий – это единственный способ сделать это с помощью @IdClass и JPA 1.0 AFAIK. См. Http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequision#Primary_Keys_through_OneToOne_Relationships . Я буду рассматривать только случаи 1 и 2.
В: Каким образом предпочтительным местом является «insertable = false, updatable = false» вообще?
- Лучшая практика получения EntityManagerFactory
- Spring-Data FETCH JOIN with Paging не работает
- Java, JPA, Glassfish, Invalid resource: jdbc / __ default__pm
- Создать JPA EntityManager без файла конфигурации persistence.xml
- В чем разница между интерфейсами CrudRepository и JpaRepository в Spring Data JPA?
У меня возникли проблемы с Hibernate по этому вопросу. Например, Hibernate 3.5.x будет жаловаться на таблицу Zips
CREATE TABLE Zips ( country_code CHAR(2), code VARCHAR(10), PRIMARY KEY (country_code, code), FOREIGN KEY (country_code) REFERENCES Countries (iso_code) )
с:
org.hibernate.MappingException: Repeated column in mapping for entity: com.kawoolutions.bbstats.model.Zip column: country_code (should be mapped with insert="false" update="false") org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:676) org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:698) ...
Как видите, столбец country_code представляет собой как PK, так и FK. Вот его classы:
Класс сущности:
@Entity @Table(name = "Zips") public class Zip implements Serializable { @EmbeddedId private ZipId id; @ManyToOne @JoinColumn(name = "country_code", referencedColumnName = "iso_code") private Country country = null; ... }
Составной class PK:
@Embeddable public class ZipId implements Serializable { @Column(name = "country_code", insertable = false, updatable = false) private String countryCode; @Column(name = "code") private String code; ... }
При установке insertable = false, updatable = false в @JoinColumn ассоциации classов сущности все исключения исчезают, и все работает нормально. Однако я не понимаю, почему приведенный выше код не должен работать. Возможно, у Hibernate возникли проблемы с этим. Является ли описанная ошибка Hibernate, поскольку она, похоже, не оценивает @Column “insertable = false, updatable = false”?
В сущности, какой стандартный метод JPA, лучшая практика или предпочтение, где поставить «insertable = false, updatable = false»?
- Безмолвно игнорируется remove ()
- Hibernate, @SequenceGenerator и allocSize
- Может javax.persistence.Query.getResultList () вернуть null?
- Spring Data JPA отображает исходный результат запроса на Non-Entity POJO
- Правильное использование флеша () в JPA / Hibernate
- JPA OneToMany, не удаляющий ребенка
- Как использовать TomEE с Hibernate
- ImprovedNamingStrategy больше не работает в Hibernate 5
Позвольте мне ответить шаг за шагом.
1. Когда вам нужно `insertable = false, updatable = false`?
Давайте посмотрим на приведенное ниже отображение,
public class Zip { @ManyToOne @JoinColumn(name = "country_code", referencedColumnName = "iso_code") private Country country = null @Column(name = "country_code") private String countryCode; }
Здесь мы имеем в виду тот же столбец в таблице, используя два разных свойства. В приведенном ниже коде,
Zip z = new Zip(); z.setCountry(getCountry("US")); z.setCountryCode("IN"); saveZip(z);
Что здесь будет спячка?
Чтобы предотвратить такую несогласованность, hibernate просит указать точку обновления отношений судов. Это означает, что вы можете ссылаться на один и тот же столбец в таблице n
раз, но только один из них может быть использован для обновления, а все остальные будут прочитаны только .
2. Почему hibernate жалуется на ваше сопоставление?
В вашем classе Zip
вы ссылаетесь на Embedded id class ZipId
который снова содержит код страны. Как и в приведенном выше сценарии, теперь у вас есть возможность обновить столбец counry_code
из двух мест. Следовательно, ошибка, заданная спящим состоянием, является правильной.
3. Как исправить это в вашем случае?
Нет. В идеале вы хотите, чтобы ваш class ZipId
генерировал идентификатор, поэтому вы не должны добавлять insertable = false, updatable = false
в код страны внутри ZipId
. Таким образом, исправление, как показано ниже, изменяет сопоставление стран в вашем Zip
classе, как показано ниже,
@ManyToOne @JoinColumn(name = "country_code", referencedColumnName = "iso_code", insertable = false, updatable = false) private Country country;
Надеюсь, это поможет вашему пониманию.
Вы также можете решить эту проблему, используя аннотацию @PrimaryKeyJoinColumn
. Аннотации PrimaryKeyJoinColumn задают столбец первичного ключа, который используется в качестве внешнего ключа для присоединения к другой таблице.
Аннотации PrimaryKeyJoinColumn используются для объединения первичной таблицы подclassа сущности в страtagsи сопоставления JOINED с основной таблицей его суперclassа; он используется в annotations SecondaryTable для присоединения вторичной таблицы к первичной таблице; и он может использоваться в сопоставлении OneToOne, в котором первичный ключ ссылочного объекта используется в качестве внешнего ключа для ссылочного объекта. Если аннотация PrimaryKeyJoinColumn не указана для подclassа в страtagsи сопоставления JOINED, предполагается, что столбцы внешнего ключа имеют те же имена, что и столбцы первичного ключа в первичной таблице суперclassа.