Фильтрация коллекции «многие ко многим» в режиме гибернации - PullRequest
4 голосов
/ 25 февраля 2010

У меня есть следующий POJO с набором внутри:

class Word {
    private Long id;
    private String word;
    private int type = WordListFactory.TYPE_DEFAULT;

    private Set<Word> refs = new HashSet<Word>();
...
}

Вот XML-код:

  <class name="kw.word.Word" table="word">
        <id name="id" column="id"  unsaved-value="null">
            <generator class="native"/>
        </id>

        <property name="word"
                  unique="true"
                  not-null="true"/>
        <property name="type"/>

        <set name="refs"
             table="word_key"
             cascade="save-update">

            <key column="word_id"/>
            <many-to-many class="kw.word.Word" 
                   column="word_ref_id"
                   fetch="join">                         
            </many-to-many>                            
        </set>


    </class>

Существует две таблицы: word и word_key . Последний связывает слово «родители» со словом «дети».

Я пытаюсь реализовать фильтрацию элементов при получении данных из БД. Полученный набор объектов должен содержать только элементы определенного типа.

Я пробовал разные вещи:

  • Использование фильтрации в отображении как (извините за отсутствие скобок)
    
      many-to-many class="kw.word.Word"
                  column="word_ref_id"
                  fetch="join">
         filter name="word_type" condition="type=:type"          
     many-to-many

В коде, который выбирает данные, я включил фильтр и установил параметр. Согласно журналам, hibernate, похоже, игнорирует этот конкретный фильтр, поскольку в результирующем SQL-запросе нет условий.

  • Использование дополнительного условия в критериях

      Word result = null;
    
    session.beginTransaction();
    
    Criteria crit = session.createCriteria(Word.class);       
    
    crit.add(Restrictions.like("word", key))
         .createAlias("refs", "r")
         .add(Restrictions.eq("r.type", getType()));//added alias and restriction for type
    
     List list = crit.list();
    
     if(!list.isEmpty())
         result = list.get(0);   
    
     session.getTransaction().commit();

теперь получающийся SQL выглядит нормально

   select
        this_.id as id0_1_,
        this_.word as word0_1_,
        this_.type as type0_1_,
        refs3_.word_id as word1_,
        r1_.id as word2_,
        r1_.id as id0_0_,
        r1_.word as word0_0_,
        r1_.type as type0_0_ 
    from
        word this_ 
    inner join
        word_key refs3_ 
            on this_.id=refs3_.word_id 
    inner join
        word r1_ 
            on refs3_.word_ref_id=r1_.id 
    where
        this_.word like ? 
        and r1_.type=?

но сразу после этого запроса есть еще один, который выбирает все элементы

 select
        refs0_.word_id as word1_1_,
        refs0_.word_ref_id as word2_1_,
        word1_.id as id0_0_,
        word1_.word as word0_0_,
        word1_.type as type0_0_ 
    from
        word_key refs0_ 
    left outer join
        word word1_ 
            on refs0_.word_ref_id=word1_.id 
    where
        refs0_.word_id=?

Может я что-то не так делаю?

1 Ответ

3 голосов
/ 26 февраля 2010

Из приведенного вами фрагмента кода несколько баллов:

  • В случае отношения «многие ко многим» вам потребуется 3 таблицы, две таблицы сущностей и одна таблица соединений. Но так как у вас одна и та же сущность -Word, я думаю, что данная структура таблицы и сопоставления выглядят хорошо.
  • Попробуйте использовать HQL и укажите 'LEFT JOIN FETCH', чтобы указать, какие ассоциации вам нужно получить в исходном SQL SELECT.

См. Эту ссылку, связанную с отношением «многие ко многим», но они использовали критерий запроса.

Запрос отношений ManyToMany с критериями Hibernate

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