To make it short: hibernate doesn't support projections and query by example? I found this post:
The code is this:
User usr = new User();
usr.setCity = 'TEST';
getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Example.create(usr))
Like the other poster said, The generated sql keeps having a where class refering to just y0_= ? instead of this_.city.
I already tried several approaches, and searched the issue tracker but found nothing about this.
I even tried to use Projection alias and Transformers, but it does not work:
User usr = new User();
usr.setCity = 'TEST';
getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Example.create(usr)).setResultTransformer(Transformers.aliasToBean(User.class));
Has anyone used projections and query by example ?
This question is related to
java
hibernate
criteria
projection
The problem seems to happen when you have an alias the same name as the objects property. Hibernate seems to pick up the alias and use it in the sql. I found this documented here and here, and I believe it to be a bug in Hibernate, although I am not sure that the Hibernate team agrees.
Either way, I have found a simple work around that works in my case. Your mileage may vary. The details are below, I tried to simplify the code for this sample so I apologize for any errors or typo's:
Criteria criteria = session.createCriteria(MyClass.class)
.setProjection(Projections.projectionList()
.add(Projections.property("sectionHeader"), "sectionHeader")
.add(Projections.property("subSectionHeader"), "subSectionHeader")
.add(Projections.property("sectionNumber"), "sectionNumber"))
.add(Restrictions.ilike("sectionHeader", sectionHeaderVar)) // <- Problem!
.setResultTransformer(Transformers.aliasToBean(MyDTO.class));
Would produce this sql:
select
this_.SECTION_HEADER as y1_,
this_.SUB_SECTION_HEADER as y2_,
this_.SECTION_NUMBER as y3_,
from
MY_TABLE this_
where
( lower(y1_) like ? )
Which was causing an error: java.sql.SQLException: ORA-00904: "Y1_": invalid identifier
But, when I changed my restriction to use "this", like so:
Criteria criteria = session.createCriteria(MyClass.class)
.setProjection(Projections.projectionList()
.add(Projections.property("sectionHeader"), "sectionHeader")
.add(Projections.property("subSectionHeader"), "subSectionHeader")
.add(Projections.property("sectionNumber"), "sectionNumber"))
.add(Restrictions.ilike("this.sectionHeader", sectionHeaderVar)) // <- Problem Solved!
.setResultTransformer(Transformers.aliasToBean(MyDTO.class));
It produced the following sql and my problem was solved.
select
this_.SECTION_HEADER as y1_,
this_.SUB_SECTION_HEADER as y2_,
this_.SECTION_NUMBER as y3_,
from
MY_TABLE this_
where
( lower(this_.SECTION_HEADER) like ? )
Thats, it! A pretty simple fix to a painful problem. I don't know how this fix would translate to the query by example problem, but it may get you closer.
The problem seems to happen when you have an alias the same name as the objects property. Hibernate seems to pick up the alias and use it in the sql. I found this documented here and here, and I believe it to be a bug in Hibernate, although I am not sure that the Hibernate team agrees.
Either way, I have found a simple work around that works in my case. Your mileage may vary. The details are below, I tried to simplify the code for this sample so I apologize for any errors or typo's:
Criteria criteria = session.createCriteria(MyClass.class)
.setProjection(Projections.projectionList()
.add(Projections.property("sectionHeader"), "sectionHeader")
.add(Projections.property("subSectionHeader"), "subSectionHeader")
.add(Projections.property("sectionNumber"), "sectionNumber"))
.add(Restrictions.ilike("sectionHeader", sectionHeaderVar)) // <- Problem!
.setResultTransformer(Transformers.aliasToBean(MyDTO.class));
Would produce this sql:
select
this_.SECTION_HEADER as y1_,
this_.SUB_SECTION_HEADER as y2_,
this_.SECTION_NUMBER as y3_,
from
MY_TABLE this_
where
( lower(y1_) like ? )
Which was causing an error: java.sql.SQLException: ORA-00904: "Y1_": invalid identifier
But, when I changed my restriction to use "this", like so:
Criteria criteria = session.createCriteria(MyClass.class)
.setProjection(Projections.projectionList()
.add(Projections.property("sectionHeader"), "sectionHeader")
.add(Projections.property("subSectionHeader"), "subSectionHeader")
.add(Projections.property("sectionNumber"), "sectionNumber"))
.add(Restrictions.ilike("this.sectionHeader", sectionHeaderVar)) // <- Problem Solved!
.setResultTransformer(Transformers.aliasToBean(MyDTO.class));
It produced the following sql and my problem was solved.
select
this_.SECTION_HEADER as y1_,
this_.SUB_SECTION_HEADER as y2_,
this_.SECTION_NUMBER as y3_,
from
MY_TABLE this_
where
( lower(this_.SECTION_HEADER) like ? )
Thats, it! A pretty simple fix to a painful problem. I don't know how this fix would translate to the query by example problem, but it may get you closer.
The real problem here is that there is a bug in hibernate where it uses select-list aliases in the where-clause:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-817
Just in case someone lands here looking for answers, go look at the ticket. It took 5 years to fix but in theory it'll be in one of the next releases and then I suspect your issue will go away.
The real problem here is that there is a bug in hibernate where it uses select-list aliases in the where-clause:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-817
Just in case someone lands here looking for answers, go look at the ticket. It took 5 years to fix but in theory it'll be in one of the next releases and then I suspect your issue will go away.
ProjectionList pl = Projections.projectionList();
pl.add(Projections.property("id"));
pl.add(Projections.sqlProjection("abs(`pageNo`-" + pageNo + ") as diff", new String[] {"diff"}, types ), diff); ---- solution
crit.addOrder(Order.asc("diff"));
crit.setProjection(pl);
ProjectionList pl = Projections.projectionList();
pl.add(Projections.property("id"));
pl.add(Projections.sqlProjection("abs(`pageNo`-" + pageNo + ") as diff", new String[] {"diff"}, types ), diff); ---- solution
crit.addOrder(Order.asc("diff"));
crit.setProjection(pl);
I'm facing a similar problem. I'm using Query by Example and I want to sort the results by a custom field. In SQL I would do something like:
select pageNo, abs(pageNo - 434) as diff
from relA
where year = 2009
order by diff
It works fine without the order-by-clause. What I got is
Criteria crit = getSession().createCriteria(Entity.class);
crit.add(exampleObject);
ProjectionList pl = Projections.projectionList();
pl.add( Projections.property("id") );
pl.add(Projections.sqlProjection("abs(`pageNo`-"+pageNo+") as diff", new String[] {"diff"}, types ));
crit.setProjection(pl);
But when I add
crit.addOrder(Order.asc("diff"));
I get a org.hibernate.QueryException: could not resolve property: diff exception. Workaround with this does not work either.
PS: as I could not find any elaborate documentation on the use of QBE for Hibernate, all the stuff above is mainly trial-and-error approach
I'm facing a similar problem. I'm using Query by Example and I want to sort the results by a custom field. In SQL I would do something like:
select pageNo, abs(pageNo - 434) as diff
from relA
where year = 2009
order by diff
It works fine without the order-by-clause. What I got is
Criteria crit = getSession().createCriteria(Entity.class);
crit.add(exampleObject);
ProjectionList pl = Projections.projectionList();
pl.add( Projections.property("id") );
pl.add(Projections.sqlProjection("abs(`pageNo`-"+pageNo+") as diff", new String[] {"diff"}, types ));
crit.setProjection(pl);
But when I add
crit.addOrder(Order.asc("diff"));
I get a org.hibernate.QueryException: could not resolve property: diff exception. Workaround with this does not work either.
PS: as I could not find any elaborate documentation on the use of QBE for Hibernate, all the stuff above is mainly trial-and-error approach
I do not really think so, what I can find is the word "this." causes the hibernate not to include any restrictions in its query, which means it got all the records lists. About the hibernate bug that was reported, I can see it's reported as fixed but I totally failed to download the Patch.
I do not really think so, what I can find is the word "this." causes the hibernate not to include any restrictions in its query, which means it got all the records lists. About the hibernate bug that was reported, I can see it's reported as fixed but I totally failed to download the Patch.
Source: Stackoverflow.com