如何映射“insert=”false”更新=“假””在复合 ID 键属性上,该属性也用于一对多 FK 中?
我正在使用现有数据库模式开发遗留代码库。现有代码使用 SQL 和 PL/SQL 在数据库上执行查询。我们的任务是使项目的一小部分与数据库引擎无关(首先,最终改变所有内容)。我们选择使用 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 不支持。我也尝试将其更改为关键多对一元素,但这也不起作用。那么...
如何将“insert='false' update='false'”映射到也在一对多 FK 中使用的复合 ID 键属性上?
I am working on a legacy code base with an existing DB schema. The existing code uses SQL and PL/SQL to execute queries on the DB. We have been tasked with making a small part of the project database-engine agnostic (at first, change everything eventually). We have chosen to use Hibernate 3.3.2.GA and "*.hbm.xml" mapping files (as opposed to annotations). Unfortunately, it is not feasible to change the existing schema because we cannot regress any legacy features.
The problem I am encountering is when I am trying to map a uni-directional, one-to-many relationship where the FK is also part of a composite PK. Here are the classes and mapping file...
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>
This code works just fine for SELECT and INSERT of a Company with names. I encountered a problem when I tried to update and existing record. I received a BatchUpdateException and after looking through the SQL logs I saw Hibernate was trying to do something stupid...
update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=?
Hibernate was trying to dis-associate child records before updating them. The problem is that this field is part of the PK and not-nullable. I found the quick solution to make Hibernate not do this is to add "not-null='true'" to the "key" element in the parent mapping. SO now may mapping looks like this...
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>
This mapping gives the exception...
org.hibernate.MappingException: Repeated column in mapping for entity: companyName column: COMPANY_ID (should be mapped with insert="false" update="false")
My problem now is that I have tryed to add these attributes to the key-property element but that is not supported by the DTD. I have also tryed changing it to a key-many-to-one element but that didn't work either. So...
How can I map "insert='false' update='false'" on a composite-id key-property which is also used in a one-to-many FK?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为您正在寻找的注释是:
并且您应该能够在 hbm.xml 中使用类似的映射,如下所示(在 23.4.2 中):
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-mappings.html
I think the annotation you are looking for is:
And you should be able to use similar mappings in a hbm.xml as shown here (in 23.4.2):
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-mappings.html
“Dino TW”提供了评论的链接 Hibernate 映射异常:具有重要信息的实体映射中的重复列。
链接提示在集合映射中提供“inverse=true”,我尝试了一下,它确实有效。 Set 和 Composite key 结合在一起的情况非常罕见。使 inverse=true,我们保留 insert &使用复合键更新表由其自身负责。
以下是所需的映射,
"Dino TW" has provided the link to the comment Hibernate Mapping Exception : Repeated column in mapping for entity which has the vital information.
The link hints to provide "inverse=true" in the set mapping, I tried it and it actually works. It is such a rare situation wherein a Set and Composite key come together. Make inverse=true, we leave the insert & update of the table with Composite key to be taken care by itself.
Below can be the required mapping,