Hibernate:在涉及外键的复合主键的情况下,insertable = false,updatable = false 属于哪里?

10 浏览
0 Comments

Hibernate:在涉及外键的复合主键的情况下,insertable = false,updatable = false 属于哪里?

在使用Hibernate或其他ORM实现复合主键时,对于使用标识关系(作为主键的外键)的复合主键组合,有多达三个地方可以放置insertable = false, updatable = false:

  1. 放置在复合主键类的@Column注解中(仅适用于@Embeddable类)或
  2. 放置在实体类的关联@JoinColumn/s注解中或
  3. 放置在实体类的冗余主键属性的@Column注解中(仅适用于@IdClass类)

第三种方式是在@IdClass和JPA 1.0中实现的唯一方式。详见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列既是主键又是外键。以下是相关的类:

实体类:

@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;
...
}

复合主键类:

@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"放置在哪里?

0