Hibernate:insertable = false,updatable = false 属于涉及外键的复合主键星座中的哪里?
Posted
技术标签:
【中文标题】Hibernate:insertable = false,updatable = false 属于涉及外键的复合主键星座中的哪里?【英文标题】:Hibernate: Where do insertable = false, updatable = false belong in composite primary key constellations involving foreign keys? 【发布时间】:2011-04-09 20:26:51 【问题描述】:在 Hibernate 或其他 ORM 中实现复合主键时,在使用标识关系的复合主键星座(作为 PK 的一部分的 FK)中,最多可以在三个位置放置 insertable = false、updatable = false:
-
进入复合 PK 类的 @Column 注释(仅限 @Embeddable 类)或
进入实体类的关联@JoinColumn/s注解或
进入实体类的冗余 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”放置在哪种方式的首选位置?
我在使用 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, updatable = false"?
本质上,什么是标准 JPA 方式、最佳实践或将“insertable = false, updatable = false”放在哪里的偏好?
【问题讨论】:
您尝试以下答案了吗?我没有看到任何 cmets 或接受的答案。我知道它可能会迟到,但它会对以后访问此页面的任何人有所帮助。谢谢。 ManuPK,从那以后我就注意到了你的回答。但是,我将不得不对此进行更深入的研究,这目前是不可能的。 【参考方案1】:让我一步一步回答。
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 会在这里做什么?
为了防止这种不一致,Hibernate 要求您指定关系的更新点。这意味着您可以多次引用表格n
中的同一列,但其中只有一个可用于更新,而所有其他将是只读的。
2。为什么 Hibernate 抱怨您的映射?
在您的 Zip
类中,您指的是 Embedded id 类 ZipId
,它再次包含国家代码。与上述情况一样,现在您可以从两个位置更新country_code
列。因此,Hibernate 给出的错误是正确的。
3。在您的情况下如何解决?
没有。理想情况下,您希望您的 ZipId
类生成 id,因此您不应将 insertable = false, updatable = false
添加到 ZipId
内的 countryCode 中。所以修复如下修改Zip
类中的country
映射如下,
@ManyToOne
@JoinColumn(name = "country_code", referencedColumnName = "iso_code",
insertable = false, updatable = false)
private Country country;
希望这有助于您的理解。
【讨论】:
【参考方案2】:你也可以使用@PrimaryKeyJoinColumn
注解来解决这个问题。 PrimaryKeyJoinColumn 注释指定一个主键列,用作连接到另一个表的外键。
PrimaryKeyJoinColumn注解用于JOINED映射策略中实体子类的主表与其超类的主表的join;它在 SecondaryTable 注释中用于将辅助表连接到主表;它可以用于 OneToOne 映射,其中引用实体的主键用作被引用实体的外键。 如果JOINED映射策略中没有为子类指定PrimaryKeyJoinColumn注解,则假定外键列与超类的主表的主键列同名。
【讨论】:
以上是关于Hibernate:insertable = false,updatable = false 属于涉及外键的复合主键星座中的哪里?的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate中“insertable = false”和“transient”之间的区别
PostgreSql Partition + Hibernate Insert
hibernate------java-delete-insert-update
Hibernate插入错误:GenericJDBCException: could not insert: