I\'m looking for a builder for HQL in Java. I want to get rid of things like:
StringBuilder builder = new StringBuilder()
.append(\"select stock from \")
@Sébastien Rocca-Serra
select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.bonus.id = bonus.id
That's just a join. Hibernate does it automatically, if and only if you've got the mapping between Stock
and Bonus
setup and if bonus
is a property of Stock
. Criteria.list()
will return Stock
objects and you just call stock.getBonus()
.
Note, if you want to do anything like
select stock
from com.something.Stock as stock
where stock.bonus.value > 1000000
You need to use Criteria.createAlias(). It'd be something like
session.createCriteria(Stock.class).createAlias("bonus", "b")
.add(Restrictions.gt("b.value", 1000000)).list()
Take a look at the search package available from the hibernate-generic-dao project. This is a pretty decent HQL Builder implementation.
@Sébastien Rocca-Serra
Now we're getting somewhere concrete. The sort of join you're trying to do isn't really possible through the Criteria API, but a sub-query should accomplish the same thing. First you create a DetachedCriteria
for the bonus table, then use the IN
operator for someValue
.
DetachedCriteria bonuses = DetachedCriteria.forClass(Bonus.class);
List stocks = session.createCriteria(Stock.class)
.add(Property.forName("someValue").in(bonuses)).list();
This is equivalent to
select stock
from com.something.Stock as stock
where stock.someValue in (select bonus.id from com.something.Bonus as bonus)
The only downside would be if you have references to different tables in someValue
and your ID's are not unique across all tables. But your query would suffer from the same flaw.
For another type-safe query dsl, I recommend http://www.torpedoquery.org. The library is still young but it provides type safety by directly using your entity's classes. This means early compiler errors when the query no longer applies before of refactoring or redesign.
I also provided you with an example. I think from your posts that you where trying to do a subquery restriction, so I based the exemple on that:
import static org.torpedoquery.jpa.Torpedo.*;
Bonus bonus = from(Bonus.class);
Query subQuery = select(bonus.getId());
Stock stock = from(Stock.class);
where(stock.getSomeValue()).in(subQuery);
List<Stock> stocks = select(stock).list(entityManager);
Criteria API does not provide all functionality avaiable in HQL. For example, you cannot do more than one join over the same column.
Why don't you use NAMED QUERIES? The look much more clean:
Person person = session.getNamedQuery("Person.findByName")
.setString(0, "Marcio")
.list();