-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: duplicate elements inside mapped bags when using criteria
PostPosted: Wed May 11, 2005 8:15 pm 
Newbie

Joined: Wed May 11, 2005 8:02 pm
Posts: 1
I'm seeing a weird problem with duplicate elements showing up in bags when using the Criteria API. Basically, in the example below there Project objects, which have a many-to-one relationship to Program, which itself has a many-to-many relationship to Attribute (represented as a bag). When we get a collection of projects using the Criteria API, hibernate pulls in the Program and Attribute tables with left outer joins, and the Attributes associated with each Program are duplicated as many times as there are Projects. For example, if the criteria matched 2 Projects, both of which mapped to the same Program, which itself has 3 Attributes, Program.getAttributes() would return a List of *6* Attributes rather than 3.

Note that if the Criteria query is replaced with an HQL one (as shown below), the problem is solved. Also, I know that changing the bags to sets would also solve the problem. Neither is a particularly appropriate solution in this particular situation for me, unfortunately.

Also, I know that the Criteria queries return duplicate objects - the problem here is not in the list returned by the query, but in the Collections that are set into the objects created by Hibernate.

Please let me know if you've seen anything similar and/or know the solution. Thanks!

-Dan

Hibernate version:
2.1.7

Mapping documents:
<class name="com.carbonfive.test.CalendarEntity2" table="test_calendar_entity" discriminator-value="CalendarEntity" batch-size="50">

<cache usage="read-write"/>

<id name="id" column="id" type="integer">
<generator class="native"/>
</id>

<discriminator column="discriminator"/>

<property name="name" column="name" type="string" length="255"/>

<bag name="attributes" table="test_calendar_entity_attribute_map" outer-join="true" cascade="none" batch-size="50">
<cache usage="read-write"/>
<key column="calendar_entity_id"/>
<many-to-many class="com.carbonfive.test.Attribute2" column="attribute_id"/>
</bag>

<subclass name="com.carbonfive.test.Project2" discriminator-value="Project">

<many-to-one name="program" class="com.carbonfive.test.Program2" column="program_id" cascade="none" foreign-key="FK_project_program"/>
</subclass>

<subclass name="com.carbonfive.test.Program2" discriminator-value="Program">

<bag name="projects" inverse="true" lazy="true" cascade="all" batch-size="50" >
<cache usage="read-write"/>
<key column="program_id"/>
<one-to-many class="com.carbonfive.test.Project2"/>
</bag>

</subclass>

</class>

<class name="com.carbonfive.test.Attribute2" table="test_attribute" batch-size="10">

<cache usage="read-write"/>

<id name="id" column="id" type="integer">
<meta attribute="use-in-equals">true</meta>
<generator class="native"/>
</id>

<property name="name" column="name" type="string" length="255"><meta attribute="use-in-equals">true</meta></property>
</class>

Code between sessionFactory.openSession() and session.close():
Criteria criteria = session.createCriteria(Project2.class);
criteria.add(Expression.in("id", projectids));
Collection projects = criteria.list();

/*
// doing this instead of the Criteria fixes the problem
Collection projects = HibernateUtil.getSession()
.createQuery("from Project2 p where p.id in ( :ids )")
.setParameterList("ids", projectids)
.list();
*/

Program2 program = ((Project2) projects.iterator().next()).getProgram();
assertEquals("Attributes should be unique",
new HashSet(program.getAttributes()).size(),
program.getAttributes().size());

Name and version of the database you are using:
SQL Server 8

The generated SQL (show_sql=true):
select this.id as id2_, this.program_id as program_id2_, this.name as name2_, program21_.id as id0_, program21_.name as name0_, attributes2_.calendar_entity_id as calendar1___, attributes2_.attribute_id as attribut2___, attribute23_.id as id1_, attribute23_.name as name1_ from test_calendar_entity this left outer join test_calendar_entity program21_ on this.program_id=program21_.id left outer join test_calendar_entity_attribute_map attributes2_ on program21_.id=attributes2_.calendar_entity_id left outer join test_attribute attribute23_ on attributes2_.attribute_id=attribute23_.id where this.id in (?, ?) and this.discriminator='Project'


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 20, 2005 1:13 pm 
Newbie

Joined: Tue May 25, 2004 9:56 am
Posts: 19
I think you need to use
Code:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
or
Code:
criteria.setResultTransformer(Criteria.ROOT_ENTITY);


I'm not sure the exact difference between the two. It seems that if the list doesn't duplicate objects, they act the same.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.