-->
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.  [ 6 posts ] 
Author Message
 Post subject: Criteria query on same association twice with aliases
PostPosted: Fri Mar 25, 2005 8:38 am 
Newbie

Joined: Sun Oct 12, 2003 4:21 pm
Posts: 16
Location: Stockholm, Sweden
Is it not possible to use the Criteria API when querying on same association twice and using aliases?
I have a HQL version that works as expected, but I really like to use the Criteria API for this, to avoid a lot of string concatenation.
I have an association called "properties" from Person and I want to query for people with propery "a" having value "x" and property "b" having value "y".
Are sub selects better in this situation? Good query performance is important.

Hibernate version: 3.0rc1

Mapping documents:
Code:
<class name="Person" table="person">
...
<set name="properties" table="personproperty" inverse="true" cascade="all,delete-orphan">
  <key column="owner"/>
  <one-to-many class="PersonProperty"/>
</set>
...

Code:
<class name="PersonProperty" table="personproperty">
...
<many-to-one name="metadata" not-null="true"/>
<many-to-one name="owner" class="Person" access="field" not-null="true"/>
<property name="dateValue" type="date" access="field">
  <column name="datevalue"/>
</property>
<property name="numericValue" type="double" access="field">
  <column name="numericvalue"/>
</property>
<property name="stringValue" type="string" access="field">
  <column name="stringvalue" length="255"/>
</property>
...

Code:
<class name="PropertyMetadata" table="propertymetadata">
...
<property name="code">
<column name="code" length="20" not-null="true"/>
</property>
<property name="description">
<column name="description" length="100" not-null="true"/>
</property>


Code between sessionFactory.openSession() and session.close():
This code works, it is using HQL.
Code:
PropertyMetadata md1 = getMetadata(session, "age", PropertyMetadata.NUMERIC);
PropertyMetadata md2 = getMetadata(session, "date", PropertyMetadata.DATE);
Collection list = session.createQuery("select distinct p from Person as p
join p.properties as a join p.properties as b
where (a.metadata = :md1 and a.numericValue = :num) and (b.metadata = :md2 and b.dateValue <= :date)")
.setEntity("md1", md1).setEntity("md2", md2).setInteger("num",42).setDate("date", new Date()).list();

This code does not work, it uses the Criteria API but I'm note sure I got it right.
Code:
PropertyMetadata md1 = getMetadata(session, "age", PropertyMetadata.NUMERIC);
PropertyMetadata md2 = getMetadata(session, "date", PropertyMetadata.DATE);
Criteria crit0 = session.createCriteria(Person.class);
crit0.setResultTransformer(new DistinctRootEntityResultTransformer());
Criteria crit1 = crit0.createAlias("properties", "p1");
Criteria crit2 = crit0.createAlias("properties", "p2");
crit1.add(Restrictions.eq("metadata", md1));
crit1.add(Restrictions.eq("numericValue", new Double(42)));
crit2.add(Restrictions.eq("metadata", md2));
crit2.add(Restrictions.le("dateValue", new Date()));
Collection list = crit0.list();


Full stack trace of any exception that occurs:
Code:
org.hibernate.QueryException: duplicate association path: properties
at org.hibernate.loader.criteria.CriteriaQueryTranslator.createAssociationPathCriteriaMap(CriteriaQueryTranslator.java:138)
at org.hibernate.loader.criteria.CriteriaQueryTranslator.<init>(CriteriaQueryTranslator.java:80)
at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:69)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1228)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:299)
at research.test.PropertyTest.testFindMultiplePropertyCriteria(PropertyTest.java:187)
...


Name and version of the database you are using: MySQL 4.1

The generated SQL (show_sql=true):
This is the SQL generated from the HQL example that works. The failing example does not output any SQL since it fails early.
select distinct person0_.id as id, person0_.first_name as first2_9_, person0_.middle_name as middle3_9_,
person0_.last_name as last4_9_ from person person0_ inner join personproperty properties1_ on person0_.id=properties1_.owner
inner join personproperty properties2_ on person0_.id=properties2_.owner where (properties1_.metadata=?
and properties1_.numericvalue=? and properties2_.metadata=? and properties2_.datevalue<=?)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 25, 2005 8:55 am 
Newbie

Joined: Sun Oct 12, 2003 4:21 pm
Posts: 16
Location: Stockholm, Sweden
Hmmm... maybe I'm half-way answering the question myself.
I tested sub selects in HQL and it worked.
Next I will test sub selects using criteria API...
If that works, I'll go for sub selectes using Criteria.
Code:
Collection list = session.createQuery(
"from Person as p where p.id in (select a.owner from PersonProperty a
where a.metadata=:md1 and a.numericValue=:num) and p.id in
(select b.owner from PersonProperty b where b.metadata=:md2
and b.dateValue <= :date)")
.setEntity("md1", md1).setEntity("md2", md2).setInteger("num",
42).setDate("date", new Date()).list();


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 25, 2005 12:22 pm 
Newbie

Joined: Sun Oct 12, 2003 4:21 pm
Posts: 16
Location: Stockholm, Sweden
Ok, now I got a working subquery example.
My question still is: Is this the correct way to use the Criteria API and will it be efficient if I have a few (average 3, max 10) subqueries?
Or is there another (more efficient) way to query on an association more than once i the same query?
Code:
PropertyMetadata md1 = getMetadata(session, "age", PropertyMetadata.NUMERIC);
PropertyMetadata md2 = getMetadata(session, "date", PropertyMetadata.DATE);

Criteria crit0 = session.createCriteria(Person.class);

DetachedCriteria crit1 = DetachedCriteria.forClass(PersonProperty.class);
crit1.setProjection(Projections.property("owner"));
crit1.add(Restrictions.eq("metadata", md1));
crit1.add(Restrictions.eq("numericValue", new Double(42)));

DetachedCriteria crit2 = DetachedCriteria.forClass(PersonProperty.class);
crit2.setProjection(Projections.property("owner"));
crit2.add(Restrictions.eq("metadata", md2));
crit2.add(Restrictions.le("dateValue", new Date()));

crit0.add(Subqueries.propertyIn("id", crit1));
crit0.add(Subqueries.propertyIn("id", crit2));

Collection list = crit0.list();

The generated SQL is:
Code:
select this_.id as id0_, this_.first_name as first2_15_0_, this_.middle_name as middle3_15_0_, this_.last_name as last4_15_0_ from person this_ where this_.id in (select this0__.owner as y0_ from personproperty this0__ where this0__.metadata=? and this0__.numericvalue=?) and this_.id in (select this0__.owner as y0_ from personproperty this0__ where this0__.metadata=? and this0__.datevalue<=?)

which I think is ok.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 25, 2005 6:31 pm 
Newbie

Joined: Sun Oct 12, 2003 4:21 pm
Posts: 16
Location: Stockholm, Sweden
Ok, five struggling hours later... I have tried to use a <map> collection, but I could not get an entity (PropertyMetadata) work as a key in the Map so I'm giving up. I was able to persist values, but I could never perform a query on the map.

The DetachedCriteria strategy (above) works so I'll use that for now.

But I still want to know how to store "properties" in a Map-like structure with an entity as the key in the map. The query stuff I'm not able to understand.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 20, 2006 5:34 am 
Newbie

Joined: Wed Sep 20, 2006 4:25 am
Posts: 1
By googling I found this quite old thread. I actually have the same problem. Is there someone who in the meantime has solved this issue?
Thanks for any comment
mondfinsternis


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 20, 2006 5:55 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
http://opensource.atlassian.com/project ... se/HHH-879


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.