我正在使用现有数据库架构的遗留代码库。现有代码使用SQL和PL / SQL在DB上执行查询。我们的任务是使项目数据库引擎不可知的一小部分(最初,最终改变一切)。我们选择使用 Hibernate 3.3.2.GA 和“* .hbm.xml”映射文件(而不是注释)。遗憾的是,改变现有模式是不可行的,因为我们无法回归任何遗留功能。
我遇到的问题是当我试图映射单向一对多关系时,其中FK 也是复合PK的一部分。这是类和映射文件......
CompanyEntity.java
public class CompanyEntity {
private Integer id;
private Set<CompanyNameEntity> names;
...
}
CompanyNameEntity.java
public class CompanyNameEntity implements Serializable {
private Integer id;
private String languageId;
private String name;
...
}
CompanyNameEntity.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.example">
<class name="com.example.CompanyEntity" table="COMPANY">
<id name="id" column="COMPANY_ID"/>
<set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false">
<key column="COMPANY_ID"/>
<one-to-many entity-name="vendorName"/>
</set>
</class>
<class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME">
<composite-id>
<key-property name="id" column="COMPANY_ID"/>
<key-property name="languageId" column="LANGUAGE_ID"/>
</composite-id>
<property name="name" column="NAME" length="255"/>
</class>
</hibernate-mapping>
此代码适用于具有名称的公司的SELECT和INSERT。我尝试更新和现有记录时遇到了问题。我收到了一个BatchUpdateException,在查看了SQL日志之后,我看到Hibernate试图做一些事情愚蠢的 ......
update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=?
Hibernate在更新之前试图将子记录关联起来。问题是这个字段是PK的一部分而不是可空的。我发现快速解决方案使Hibernate不这样做是为了将“not-null ='true'”添加到父映射中的“key”元素。现在可能映射看起来像这样......
CompanyNameEntity.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.example">
<class name="com.example.CompanyEntity" table="COMPANY">
<id name="id" column="COMPANY_ID"/>
<set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false">
<key column="COMPANY_ID" not-null="true"/>
<one-to-many entity-name="vendorName"/>
</set>
</class>
<class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME">
<composite-id>
<key-property name="id" column="COMPANY_ID"/>
<key-property name="languageId" column="LANGUAGE_ID"/>
</composite-id>
<property name="name" column="NAME" length="255"/>
</class>
</hibernate-mapping>
此映射提供异常......
org.hibernate.MappingException: Repeated column in mapping for entity: companyName column: COMPANY_ID (should be mapped with insert="false" update="false")
我现在的问题是我尝试将这些属性添加到key-property元素,但DTD不支持。我也尝试将它改为一个多对一的关键元素,但这也不起作用。所以......
如何在复合id键属性上映射“insert ='false'update ='false'”,该属性也用于一对多FK?
答案 0 :(得分:83)
我认为您正在寻找的注释是:
public class CompanyName implements Serializable {
//...
@JoinColumn(name = "COMPANY_ID", referencedColumnName = "COMPANY_ID", insertable = false, updatable = false)
private Company company;
你应该能够在hbm.xml中使用类似的映射,如下所示(在23.4.2中):
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-mappings.html
答案 1 :(得分:0)
“Dino TW”提供了评论Hibernate Mapping Exception : Repeated column in mapping for entity的链接,其中包含重要信息。
链接提示在集合映射中提供“inverse = true”,我尝试了它并且它实际上有效。这是一种罕见的情况,其中Set和Composite键组合在一起。使inverse = true,我们留下插入&amp;使用Composite键更新表格,以便自行处理。
下面可以是必需的映射,
<class name="com.example.CompanyEntity" table="COMPANY">
<id name="id" column="COMPANY_ID"/>
<set name="names" inverse="true" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false">
<key column="COMPANY_ID" not-null="true"/>
<one-to-many entity-name="vendorName"/>
</set>
</class>