two tables, Cat and kitten(one to many), there are 5 records in the kitten table, and 1 in the cat table. kitten have color, 2 in white and 3 in yellow. I wrote the following HQL which return the Cat.
select c from Cat c inner join c.kitten k where k.color='yellow'
this return me the cat. but when I did
cat.getKitten().size()
it returns 5, instead of 3. what I want to do is only get the matched child instead of all of them, what's the right way to do this?
seems like this do the trick, thanks zzz and everyone's effort
Session session = sessionFactory.getCurrentSession();
开发者_如何学运维 List<Object> funds = session.createQuery("select k.cat,k from kitten k where k.color='yellow'").list();
Object[] os = (Object[])funds.get(0);
Cat c = (Cat)os[0];
Kitten fc = (Kitten)os[1];
List list = new ArrayList<Kitten>();
list.add(fc);
c.setKittens(list);
this return the right thing.
In short, you don't want to select the cat, but want to select some of its kittens:
select k from Cat c inner join c.kitten k where k.color = 'yellow'
This will select 3 kitten, each having the same cat.
The query asks for all the cats with yellow kittens, but once you have the cat, you are then asking for all its associated kittens (not just the yellow ones).
We might be able to help you more if you show how you have mapped/annotated the Cat/Kitten classes.
btw that is by design. You can't filter a collection by using a restriction.
If you look closer, hibernate is going to the DB twice: once with your query, and once to get the collection.
you need to get your cat object first and then get the filtered kittens which will be lazyloaded by default.
something like
var kittens= cat.kittens.where(x->x.color="yellow")
var count=kittens.Count();
if java you could do something like this
Collection<Kitten> kittens= cat.getKittens();
Collection<Kitten> filteredKittens = filterCollection(kittens, session);
and your filterCollection method will be:
private static <T> Collection<T> filterCollection(Collection<T> collection, Session s) {
Query filterQuery = s.createFilter(collection, "where this.color='yellow'");
return filterQuery.list();
}
here is a blogpost abt it: http://www.flexpasta.com/index.php/2009/05/20/filtering-hibernate-child-collections/
based on the comments below we decided to use
select g, k from grandCat g inner join fetch g.cat c inner join fetch c.kitten k where k.color ='yellow'
and select the required content and then cast it appropriatelty.. read the comments for clarity
精彩评论