Search multiple tagged article - Hibernate many-to-many
I store articles with multiple tag as follow:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
@Entity
public class Article {
@Id
@GeneratedValue
private Integer id;
@ManyToMany
private List<Tag> tags;
private String subject;
}
and
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Tag {
@Id
private String name;
private String description;
}
And I want to search articles which contains some tags, for example, like this question hibernate
and many-to-many
. So I tried as:
import static org.hibernate.criterion.Restrictions.*;
// ...
Criteria criteria = session.createCriteria(Article.class);
Criteria tagCriteria = criteria.createCriteria("tags");
tagCriteria.add(and(eq("name", "hibernate"), eq("name", "many-to-many")));
@SuppressWarnings("unchecked")
List<Article> list = criteria.list();
but, does not works and returned list is empty because logged SQL shows as:
select
this_.id as id1_1_,
this_.subject as subject1_1_,
tags3_.Article_id as Article1_,
tag1_.name as tags2_,
tag1_.name as name0_0_,
tag1_.description as descript2_0_0_
from
Article this_
inner join Article_Tag tags3_ on this_.id=tags3_.Article_id
inner join Tag tag1_ on tags3_.tags_name=tag1_.name
where
tag1_.name=? // assign 'hibernate'
and
tag1_.name=? // assign 'many-to-many'
When replace and
to or
returns too many articles because generated SQL was ... where (tag1_.name=? or tag1_.name=?)
.
What I want exactly may looks like:
select
开发者_StackOverflow中文版 this_.id as id1_1_,
this_.subject as subject1_1_,
tags3_.Article_id as Article1_,
tag1_.name as tags4_,
tag1_.name as name0_0_,
tag1_.description as descript2_0_0_
from
Article this_
inner join Article_Tag tags3_ on this_.id=tags3_.Article_id
inner join Tag tag1_ on tags3_.tags_name=tag1_.name
// following 2 lines are added
inner join Article_Tag tags4_ on this_.id=tags4_.Article_id
inner join Tag tag5_ on tags4_.tags_name=tag5_.name
where
tag1_.name=? // assign 'hibernate'
and
tag5_.name=? // assign 'many-to-many'
Is it possible when I use HQL only?
You should try something like that:
Criteria criteria = getSession().createCriteria(Article.class);
int i=0;
for ( String tagName : tagNames ) {
String aliasName = "alias_" + i;
criteria.createAlias("tags", aliasName, Criteria.INNER_JOIN);
criteria.add( Restrictions.eq(aliasName+".name",tagName) );
i++;
}
Actually the matter is that when you do a simple inner join, ok you have joined your results with the tags but the matter is that the data is actually on 2 rows... So if you join 2 times you'll be able to get the data on one rows.
I think it's not really elegant but it should work...
精彩评论