Hibernate:Where insertable = false,updatable = false属于涉及外键的复合主键星座?

在Hibernate或其他ORM中实现复合主键时,在使用标识关系的复合主键星座(FK是PK的一部分)中,最多有三处将insertable = false,updatable = false:

  1. 进入复合PK类的@Column注解(@Embeddable类)或
  2. 进入实体类的关联@ContactColumn / s注释或
  3. 进入实体类的冗余 PK属性的@Column注解(仅限于@IdClass类)

第三个是使用@IdClass和JPA 1.0 AFAIK的唯一方法。 见http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Primary_Keys_through_OneToOne_Relationships 。 我会考虑只有案件1和2。

问:一般来说,将“insertable = false,updatable = false”放在哪个位置是最好的select?

关于这个问题,我遇到了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。 这里是它的类:

实体类:

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

复合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时,所有exception消失,一切正常。 但是,我不明白为什么上面的代码不应该工作。 这可能是Hibernate有这个问题。 是描述了一个Hibernate的bug,因为它似乎没有评估@Column“insertable = false,updatable = false”?

从本质上讲,什么是标准JPA方式,最佳实践或偏好何处放置“insertable = false,updatable = false”?

让我一步一步回答。

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")); x.setCountryCode("IN"); saveZip(z); 

冬眠会在这里做什么?

为了防止这种不一致,hibernate要求你指定关系的更新点。 这意味着你可以引用表中的同一列n次,但只有其中一个可以用来更新,而其他的只能被读取

2.为什么hibernate抱怨你的映射?

在您的Zip类中,您指的是embedded式id类ZipIdZipId包含国家/地区代码。 正如在上面的情况下,你现在可以从两个地方更新counry_code列。 因此,hibernate给出的错误是适当的。

3.如何解决你的情况?

不,理想情况下,您希望ZipId类生成id,因此您不应将insertable = false, updatable = false ZipId insertable = false, updatable = falseZipId内的countryCode。 所以修正如下修改你的zip类中的country映射如下,

 @ManyToOne @JoinColumn(name = "country_code", referencedColumnName = "iso_code", insertable = false, updatable = false) private Country country; 

希望这有助于你的理解。

你也可以使用@PrimaryKeyJoinColumn注解来解决这个问题。 PrimaryKeyJoinColumn注释指定用作外键的主键列以连接到另一个表。

PrimaryKeyJoinColumn注解用于将JOINED映射策略中的实体子类的主表连接到其超类的主表; 它在SecondaryTable注释中用于将辅助表连接到主表; 并且可以用在OneToOne映射中,其中引用实体的主键被用作被引用实体的外键。 如果在JOINED映射策略中没有为子类指定PrimaryKeyJoinColumn注释,则假定外键列与超类主表的主键列具有相同的名称。