2011-04-27 1 views
2

Je stocke des articles avec le tag multiple comme suit:Recherche multiple étiqueté article - Hibernate many-to-many

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; 

} 

et

import javax.persistence.Entity; 
import javax.persistence.Id; 

@Entity 
public class Tag { 

    @Id 
    private String name; 

    private String description; 

} 

Et je veux rechercher des articles contenant des balises, pour par exemple, comme cette question hibernate et many-to-many. J'ai donc essayé comme:

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(); 

mais, ne marche et retour liste est vide parce que SQL connecté montre que:

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' 

Quand remplacer and à or renvoie trop d'articles parce que le SQL généré était ... where (tag1_.name=? or tag1_.name=?).

Ce que je veux exactement ressemble peut:

select 
    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' 

Est-il possible quand j'utilise HQL seulement?

Répondre

1

Vous devriez essayer quelque chose comme ça:

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++; 
    } 

En fait, la question est que lorsque vous faites d'une simple jointure interne, ok vous avez rejoint vos résultats avec les balises, mais la question est que les données sont en fait sur 2 lignes ... Donc, si vous vous joignez 2 fois, vous pourrez obtenir les données sur une ligne.

Je pense que ce n'est pas vraiment élégant mais il devrait fonctionner ...

+0

Merci pour votre réponse, mais il génère une exception de 'org.hibernate.QueryException: chemin d'association en double: tags'. La chaîne de critères est 'CriteriaImpl (com.cremoi.model.article.Article: this [Sous-critère (tags: alias_0), Sous-critères (tags: alias_1)] [alias_0.name = hibernate, alias_1.name = plusieurs-à-plusieurs]) 'qui ressemble bien au travail, mais ne fonctionne pas. – leafriend

+0

J'ai trouvé une autre solution en utilisant 'Conjunction' et' DetachedCriteria': http://opensource.atlassian.com/projects/hibernate/browse/HHH-879?focusedCommentId=39793&page=com.atlassian.jira.plugin.system.issuetabpanels% 3Acomment-tabpanel # action_39793 Cela fonctionne bien mais pas élégant. Franchement, c'est tellement moche. :( – leafriend

+0

désolé je ne savais pas que ce n'était pas possible;) bonne chance –