Попытка заставить Hibernate генерировать подзапрос вместо внутренних объединений (используя Grails) - PullRequest
0 голосов
/ 25 августа 2011

Этот вопрос является своего рода продолжением вопроса, который я разместил здесь: Проблема с дубликатами, использующими функцию Grails 'withCriteria с отношением "многие ко многим"

I'mиспользуя те же 3 класса домена, определенные там, с добавлением следующего класса:

class Genre {
    int id
    String name
}

и добавленного свойства жанра в классе Question:

class Question {
    int id
    int text
    Genre genre

    static hasMany = [questionAnswers : QuestionAnswer]
}

Я пробовал 2запросы:

def criteria = Answer.createCriteria()
def listing = criteria.listDistinct() {
    cache false
    order "id", "asc"
    maxResults(10)

    questionAnswers {
        question {
            genre {
                eq("id", myGenreID)
            }
        }
    }
}

и

def criteria2 = Answer.createCriteria()
def listing2 = criteria2.listDistinct() {
    join "questionAnswers"
    join "questionAnswers.question"
    join "questionAnswers.question.genre"
    createAlias "questionAnswers", "qa"
    createAlias "qa.question", "q"
    createAlias "q.genre", "g"
    cache false
    order "id", "asc"
    maxResults(10)

    eq("g.id", myGenreID)
}

Оба запроса генерируют по существу один и тот же SQL, за исключением того, что первый генерирует левые внешние объединения, а второй генерирует внутренние объединения.Вот вывод 2-го запроса (упрощенный с помощью «select *»):

select *
from answer a
inner join question_answer qa on a.id = qa.answer_id 
inner join question q on qa.question_id = q.id 
inner join genre g on q.genre_id = g.id 
where g.id = 1 
order by a.id asc
limit 10;

Вышеприведенный SQL-код может возвращать дубликаты строк ответа, что мне не нужно, поэтому я использую функцию listDistinct дляcritQuery (альтернатива решению resultTransformer, которое я принял по указанному вопросу).

Вот проблема: функция maxResults применяется ДО функции listDistinct, поэтому, если есть какие-либо повторяющиеся строки ответа, я всегда получаю в итогеменьше 10 результатов.

Мне действительно нужен сгенерированный SQL, чтобы он выглядел примерно так:

select *
from answer a
where a.id in (select distinct qa.answer_id
               from question_answer qa
               inner join question q on qa.question_id = q.id 
               inner join genre g on q.genre_id = g.id 
               where g.id = 1)
order by a.id asc
limit 10;

Есть ли способ превратить поиск question_answer в подзапрос, как в приведенном выше SQL?

(Приношу свои извинения, если решение очень простое. Если это не было болезненно очевидно из моих вопросов, я не очень удивлен в спящем режиме.)

Любая помощь / предложения очень ценятся.

Спасибо,

BJ

1 Ответ

0 голосов
/ 26 августа 2011

Я не знаю, Grails, но в Hibernate я думаю, что то, что вы ищете, попадает под компетенцию выбор стратегии .Один из способов установить это, например, с помощью атрибута @OneToMany.fetch.Вы также можете установить стратегию выборки в запросах, как показано в этом примере из этой той же главы справочного руководства:

User user = (User) session.createCriteria(User.class)
    .setFetchMode("permissions", FetchMode.JOIN)
    .add( Restrictions.idEq(userId) )
    .uniqueResult();

Надеюсь, это поможет вам указать правильное направление.

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