Поиск статьи с несколькими тегами - Hibernate многие-ко-многим - PullRequest
2 голосов
/ 27 апреля 2011

Я храню статьи с несколькими тегами следующим образом:

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;

}

и

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

@Entity
public class Tag {

    @Id
    private String name;

    private String description;

}

И я хочу искать статьи, которые содержат некоторые теги, например, такие как hibernate и many-to-many. Поэтому я попробовал как:

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

но, не работает, и возвращаемый список пуст, потому что зарегистрированный SQL показывает как:

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'

При замене and на or возвращается слишком много статей, поскольку сгенерированный SQL был ... where (tag1_.name=? or tag1_.name=?).

То, что я хочу, может выглядеть примерно так:

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'

Возможно ли использовать только HQL?

1 Ответ

1 голос
/ 27 апреля 2011

Вы должны попробовать что-то вроде этого:

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

На самом деле дело в том, что когда вы делаете простое внутреннее объединение, хорошо, вы объединяете свои результаты с тегами, но дело в том, что данные на самом деле находятся в 2 рядах ... Так что, если вы объедините 2 раза, вы будете возможность получить данные в одну строку.

Я думаю, что это не очень элегантно, но должно работать ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...