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

Kaw*_*awu 32 java hibernate jpa relationships composite-primary-key

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

  1. 进入复合PK类'@Column注释(仅限@Embeddable类)或
  2. 进入实体类'association @ 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.我只会考虑案例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)
)
Run Code Online (Sandbox Code Playgroud)

有:

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)
...
Run Code Online (Sandbox Code Playgroud)

如您所见,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;
...
}
Run Code Online (Sandbox Code Playgroud)

复合PK类:

@Embeddable
public class ZipId implements Serializable
{
    @Column(name = "country_code", insertable = false, updatable = false)
    private String countryCode;

    @Column(name = "code")
    private String code;
...
}
Run Code Online (Sandbox Code Playgroud)

将insertable = false,updatable = false放入实体类关联的@JoinColumn时,所有异常都会消失,一切正常.但是,我不明白为什么上面的代码不应该工作.可能是Hibernate有这个问题.是描述了一个Hibernate错误,因为它似乎没有评估@Column"insertable = false,updatable = false"?

从本质上讲,标准的JPA方式,最佳实践或偏好在哪里放"insertable = false,updatable = false"?

Man*_*uPK 71

让我一步一步回答.

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;

}
Run Code Online (Sandbox Code Playgroud)

这里我们使用两个不同的属性来引用表中的相同列.在下面的代码中,

Zip z = new Zip();

z.setCountry(getCountry("US"));
z.setCountryCode("IN");

saveZip(z);
Run Code Online (Sandbox Code Playgroud)

冬眠会在这里做什么?

为了防止这种不一致,hibernate要求你指定关系船的更新点.这意味着您可以在表格中引用同一列,n但只能使用其中一列进行更新,而其他所有列都只能读取.

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

在您的Zip课程中,您指的ZipId是同样包含国家/地区代码的嵌入式ID类.如上所述,您现在可以counry_code从两个位置更新列.因此,hibernate给出的错误是正确的.

3.如何解决你的情况?

不.理想情况下,您希望您的ZipId类生成id,因此您不应该添加insertable = false, updatable = false到countryCode中ZipId.所以修复如下修改country你的Zip类中的映射,如下所示,

@ManyToOne
@JoinColumn(name = "country_code", referencedColumnName = "iso_code",
insertable =  false, updatable = false)
private Country country;
Run Code Online (Sandbox Code Playgroud)

希望这有助于您的理解.