• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Hibernate - multiple collection with restrictions mapping problem part II

 
mat novak
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,
Having send one post about multiple collection mapping, I still have a problem with it.
My first post concerning this topic can be found here - http://www.coderanch.com/t/216591/ORM/java/Hibernate-multiple-collection-restrictions-mapping

But to shortly remind my problem:

Lets's say I want to have a List of ZOO's objects.
I have a table called "zoo" with two fields:
id - id of ZOO
name - name of ZOO

Simple export from this table could look like this:
id:1 ; name:ZOO1
id:2 ; name:ZOO2
id:3 ; name:ZOO3


Then I have second table - "Animals" with four fields:
id - id of animal
zoo_id - id of zoo (this is a FK)
animal_type - describes type of animal (there can by only four types of animals: dog, cat, fish, bird)
animal_name - name of animal

A simple export from this table could look as below:
id:1 ; zoo_id:1 ; animal_type: dog ; animal_name: doggy1
id:2 ; zoo_id:1 ; animal_type: dog ; animal_name: doggy2
id:3 ; zoo_id:1 ; animal_type: cat ; animal_name: cat1
id:4 ; zoo_id:2 ; animal_type: cat ; animal_name: cat2
id:5 ; zoo_id:2 ; animal_type: fish ; animal_name: fishy1
id:6 ; zoo_id:2 ; animal_type: bird ; animal_name: bird1

Now, I want to have Java class called "ZOO" as follows:

class Zoo{
Set dogs; //can be a Hashset
Set cats;
Set fish;
Set birds;
//I ommitt the rest of the listing of this class
}

Finally, I would like to retrieve from DB the list of ZOO's with eager-fetched animals just by calling
List zooList = session.createCriteria(Zoo.class).list();


As a result I should get List with two elements
element1 - object corresponding to ZOO1 (Set dogs should contain 2 elements ; Set cats should contain 1 elements ; Set fish should contain 0 elements ; Set birds should contain 0 elements)
element2 - object corresponding to ZOO2 (Set dogs should contain 0 elements ; Set cats should contain 1 elements ; Set fish should contain 1 elements ; Set birds should contain 1 elements)


As was suggested in previus post I have two mapping files as follows:


Animal.hbm.xml:

code:


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >

<hibernate-mapping>

<class
name="org.myapp.hibernateobject.Animal"
table="ANIMAL"
discriminator-value="-1" >

<id> ..... </id>

<discriminator column="Animal_Type" type="String"/>


<property
name="name"
type="java.lang.String"
column="Animal_Name" >
</property>

<property
name="animalType"
type="String"
column="Animal_Type"
insert="false"
update="false" >
</property>

<many-to-one name="zoo" class="org.myapp.hibernateobject.Zoo" not-null="true" update="false" insert="false">
<column name="zoo_id"/>

</many-to-one>


<!-- Mapping for subclasses -->
<subclass name="org.myapp.hibernateobject.Cat" discriminator-value="Cat">
</subclass>

<subclass name="org.myapp.hibernateobject.Dog" discriminator-value="Dog">
</subclass>

<subclass name="org.myapp.hibernateobject.Fish" discriminator-value="Fish">
</subclass>

</class>
</hibernate-mapping>




Zoo.hbm.xml:

code:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >

<hibernate-mapping>

<class
name="org.myapp.hibernateobject.Zoo"
table="ZOO" >

<id>.....</id>

<property name="name"
type="java.lang.String"
column="Name" >
</property>

<set name="cats" lazy="false" inverse="true" cascade="all-delete-orphan">
<key>
<column name="id" />
</key>

<one-to-many class="org.myapp.hibernateobject.Cat" />
</set>

<set name="dogs" lazy="false" inverse="true" cascade="all-delete-orphan">
<key>
<column name="id" />
</key>

<one-to-many class="org.myapp.hibernateobject.Dog" />
</set>

<set name="fish" lazy="false" inverse="true" cascade="all-delete-orphan">
<key>
<column name="id" />
</key>

<one-to-many class="org.myapp.hibernateobject.Fish" />
</set>


</class>
</hibernate-mapping>




Of course org.myapp.hibernateobject.Cat/Dog/Fish extends org.myapp.hibernateobject.Animal

And if I call Cat/Dog/Fish class explicitly everything is ok.
i.e.
Criteria criteria = session.createCriteria(Cat.class);
List projects = criteria.list();

produces SQL like this (I simplified this a little):
(ble ble ble) where Animal_Type='Cat' (so the proper mapping and proper discriminator is chosen)

But if I call a list of ZOO's
List zooList = session.createCriteria(Zoo.class).list();

for every collection declared in ZOO class (that is: Set dogs; Set cats; Set fish; ) generated SQL looks as follows:

(ble ble ble) where zoo_id=?

and there is missing part " and Animal_Type='Dog' " ; " and Animal_Type='Cat' " ; " and Animal_Type='Fish' " respectively

Could you please tell me what do I do wrong?
 
Mark Spritzler
ranger
Sheriff
Posts: 17278
6
IntelliJ IDE Mac Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Unfortunately, you can only eager load one of the Collections. The reason behind it is that the join is an outer join, so if you tried to out join three collections you would end up with a cartesian product.

Mark
 
Arun Kumarr
Ranch Hand
Posts: 661
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hmmm.
1. Could be because youa re using a Table per class hierarchy. I suggest you use a Table per subclass, using a discriminator where you can do get the combined effect of subclassing and joining.

2. If you business still doesn't allow you to model first option, try using a filter on the Set elements. probably that should do the trick.
 
mat novak
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you very much. I think I'll try tje filter option.

Best regards
mat12345
 
Ben Warner
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hiya Mat,
Did you find a solution for this?

I'm having the same problem whereby the discriminator is not being put into the sql when lazy fetching a set of subclass entities.

Any help would be greatly appreciated.

Cheers,
Ben
 
Ben Warner
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I found a solution for his over on the hibernate forum:

http://forum.hibernate.org/viewtopic.php?t=949895&highlight=&sid=1f6d9c9c02b17d9eac2b5daedf4a38dd

You need to put force="true" in the discriminator.

<discriminator column="DETAIL_TYPE" type="string" force="true"/>
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic