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:

Hibernate的dynamic-insert和dynamic-update的使用

hibernate的save方法与sql的insert的区别