如何将多个值类型集合映射到 Hibernate 中的一个表?

Posted

技术标签:

【中文标题】如何将多个值类型集合映射到 Hibernate 中的一个表?【英文标题】:How to map many value type collections to one single table in Hibernate? 【发布时间】:2011-01-23 12:37:16 【问题描述】:

出于性能原因,我正在尝试将休眠中的许多值类型集映射到一个表。 首先,我确实将它们都放在了它们自己的表中,这导致了太多的连接。

我有一个 Categories 类,它包含许多带有一组集合的组件,然后我使用实体名称和鉴别器通过子类将它们映射到单个表。 映射 sn-p 见下文。

这很好用,但是因为包含所有集合的单个表,所以在移除组件时很难自动移除集合。这是因为它被建模为一个实体,而 Hibernate 无法发出该集合已被删除的信号。

映射细节:

<class name="com.sample.CategoriesDefault" table="dec_cats" >
 <id name="id" column="id" type="string" length="40" access="property">
  <generator class="assigned" />
 </id>
 <component name="incomeInfoMember" class="com.sample.IncomeInfoDefault">
   <property name="hasWage" type="boolean" column="inMemWage"/>
    ...
   <component name="wage" class="com.sample.impl.WageDefault">
     <property name="hasEmployerWage" type="boolean" column="inMemEmpWage"/>
      ...
     <set name="employerWages" cascade="all-delete-orphan" lazy="false">
      <key column="idCats" not-null="true" />
      <one-to-many entity-name="mIWaEmp"/>
     </set>
   </component>
 </component>
</class>

<class name="com.sample.NameValueTypeEntityMarker" table="cats_name_amount">
 <id name="id" column="id" type="string" length="40" access="property">
  <generator class="assigned" />
 </id>
 <discriminator type="string" force="true">
   <column name="objType" index="ixDiscrCatsNameAmt" length="25" not-null="true" />
 </discriminator>
 <version name="version" column="objVrs"  unsaved-value="negative"/>

 <property name="name" type="string" column="name" not-null="true" />
 <subclass name="com.sample.NameAmountsIntValueTypeEntityMarker">
  <property name="amount1" type="integer" column="amount1" access="property" not-null="true"/>
   ...
   <subclass entity-name="mIWaEmp" name="com.sample.EmployerWageDefault" discriminator-value="mIWaEmp" />
   <subclass entity-name="pIWaEmp" name="com.sample.impl.EmployerWageDefault" discriminator-value="pIWaEmp" />
 </subclass>
</class>

用法:

Categories cats = new CategoriesDefault();
Wage wage = new Wage();
Set<EmployerWage> set = new HashSet<EmployerWage>();
set.add(new EmployerWageDefault(cats));
wage.setEmployerWages(set);
IncomeMember inc = new IncomeMemberDefault();
inc.setWage(wage);
cats.setIncomeMember(inc);
cats.saveOrUpdate(); // will store it in the db.

// now remove the income:
cats.setIncomeMember(null);
cats.saveOrUpdate();
cats = getPersister().findCats(cats.getId());
// ERROR: cats still contains IncomeMember, Wage and EmployerWages.

发生此错误的原因是 EmployerWages 不会自动删除,因为它们被标记为子类别的类别(请参阅关键列),因此当类别被删除而不是当他的组件被删除时,它们将作为孤儿被删除...... 但是,我不能让 EmployerWages 成为 Wage 的孩子,因为 Wage 是一个组件,然后 Hibernate 投诉......

Pffff...很难解决这个问题。想法更受欢迎......

【问题讨论】:

【参考方案1】:

不确定这是否会有所帮助,但您是否尝试过使用鉴别器列来告诉 Hibernate 根据表中的不同条件加载哪种值类型?

http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/mapping.html#mapping-declaration-discriminator

【讨论】:

我看不出这与问题有什么关系? 说实话,这是很久以前的事了,我不记得我最初的想法了。不过,我现在真的没有足够的时间来审查它并改进答案。

以上是关于如何将多个值类型集合映射到 Hibernate 中的一个表?的主要内容,如果未能解决你的问题,请参考以下文章

映射值类型集合-003映射List(<list-index>)

映射值类型集合-002映射Bag(<idbag><collection-id>)

使用 JPA 和 Hibernate 将 Java 布尔值映射到 Oracle Number 列

如何将列表值映射到新对象属性

(转)Hibernate框架基础——一对多关联关系映射

(N)Hibernate - 是不是可以将多个表动态映射到一个类