Hibernate:insertable = false,updatable = false属于涉及外键的复合主键星座中的什么位置?

2024-03-04

在 Hibernate 或其他 ORM 中实现复合主键时,在使用标识关系(作为 PK 一部分的 FK)的复合主键星座中,最多可以在三个位置放置 insertable = false、updatable = false:

  1. 进入复合 PK 类的 @Column 注释(仅限 @Embeddable 类)或
  2. 进入实体类的关联@JoinColumn/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 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)
)

with:

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

saveZip(z);

Hibernate 会在这里做什么?

为了防止这种不一致,Hibernate 要求您指定关系的更新点。意思是您可以参考表中的同一列n次数,但只能使用其中一次更新,其他全部只读.

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

In your Zip您指的是嵌入式 id 类ZipId它再次包含国家/地区代码。正如上面的场景,现在您可以更新country_code来自两个地方的列。因此 Hibernate 给出的错误是正确的。

3.您的情况如何解决?

不。理想情况下,您希望您的ZipId类来生成id,所以你不应该添加insertable = false, updatable = false到里面的国家代码ZipId。所以修复方法如下修改country映射在你的Zip类如下,

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

希望这有助于您的理解。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hibernate:insertable = false,updatable = false属于涉及外键的复合主键星座中的什么位置? 的相关文章

随机推荐