问题
I am tring to map many value-type sets in hibernate to one table for performance reasons. First I did put them all in their own table which led to too many joins.
I have a Categories class that contains many components with a bunch of sets and then I map them to a single table through subclasses by using the entity-name and discriminator. See below for the mapping snippet.
This works fine, but because the single table that contains all the sets, it's hard to automatically remove a set when a component is removed. This is because it's modelled as an Entity and Hibernate can't signal that the set has been removed.
Mapping details:
<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>
Usage:
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.
This errors occurs as the EmployerWages aren't automatically removed as they are marked as child's of Categories (see the key column) and so they are removed as orphan's when Categories is removed and not when of his components is removed... However, I can't make EmployerWages a child of Wage as Wage is a component and Hibernate complaints then...
Pffff... very hard to solve this. Idea's are more then welcome...
回答1:
Not sure if this will help, but have you tried using a discriminator column in order to tell Hibernate which value-type to load based on different criteria within the table?
http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/mapping.html#mapping-declaration-discriminator
来源:https://stackoverflow.com/questions/4773817/how-to-map-many-value-type-collections-to-one-single-table-in-hibernate