在Hibernate或其他ORM中实现组合主键时,在使用标识关系(作为PK一部分的FK)的组合主键星座中,最多可在三个位置放置insertable = false,updatable = false。
第三种是使用@IdClass和JPA 1.0 AFAIK的唯一方法。参见http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Primary_Keys_through_OneToOne_Relationships。我将仅考虑情况1.和2。
问:通常将“ insertable = false,可更新= false”放在哪个位置是首选方法?
我在这个问题上遇到了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时,所有异常消失并且一切正常。但是,我不明白为什么上面的代码不起作用。Hibernate可能对此有问题。所描述的是Hibernate错误,因为它似乎不评估@Column“ insertable = false,可更新= false”吗?
本质上,什么是标准的JPA方法,最佳实践或在何处放置“ insertable = false,可更新= false”的首选项?
让我一步一步地回答。
insertable = false,可更新= 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在这里做什么?
为了避免这种不一致,hibernate要求您指定关系船的更新点。这意味着 您可以n多次引用表中的同一列,但是只能使用其中之一来更新,而所有其他都将是只读的。
n
在您的Zip类中,您引用的ZipId是再次包含国家/地区代码的Embedded id类。与上述情况一样,现在您可以counry_code从两个位置更新该列。因此,hibernate给出的错误是正确的。
Zip
ZipId
counry_code
不能。理想情况下,您希望您的ZipId类生成ID,因此您不应该在中添加insertable = false, updatable = falsecountryCount ZipId。因此,解决方法如下所示,如下所示修改类中的country映射Zip,
insertable = false, updatable = false
country
@ManyToOne @JoinColumn(name = "country_code", referencedColumnName = "iso_code", insertable = false, updatable = false) private Country country;
希望这有助于您的理解。