Groovy и Hibernate — высокопроизводительные запросы в отношениях «один ко многим»

#performance #hibernate #groovy

#Производительность #гибернация #groovy

Вопрос:

Я унаследовал довольно сложное приложение groovy и пытаюсь понять, как я могу лучше решить некоторые из существующих в настоящее время неприятных шаблонов запросов.

Просто у меня есть что-то вроде:

 Class A {
    User user
    Bravo bravo
    static hasMany = [foo: Foo, bar: Long]
}

Class Foo {
    User user
    Delta delta
    static belongsTo = [a: A]
    static hasMany = [woo: Woo]
}

Class Woo {
    User user
    Alpha alpha
    static belongsTo = [foo: Foo]
}
  

Я пытаюсь сделать A.findAllByUser(user) то, что возвращает мне a <List>A , однако, когда я начинаю перебирать этот список, я сталкиваюсь с сотнями запросов, которые еще bravo больше расширяются и foo .

Я попытался добавить Foo fetch:"join" к классу Foo и Woo fetch: "join" классу Woo, однако это означает, что КАЖДЫЙ запрос, который касается этих двух, всегда будет выполнять эти запросы (и все еще не решает сотни запросов bravo .

Я довольно новичок, когда дело доходит до использования HQL, однако это вызывает некоторые серьезные проблемы с производительностью и масштабированием больших запросов. Есть ли лучший способ решить эту проблему (и, надеюсь, избежать сотен запросов select)?

Комментарии:

1. Когда вы выполняете итерацию A , вы также читаете что-то из A.foo или A.bravo ? Даже toString может привести к считыванию этих полей и, следовательно, к загрузке hibernate

2. это приложение groovy или grails / gorm?

Ответ №1:

Похоже, вы используете GORM (который является ORM, используемым фреймворком Grails).

Чтобы решить вашу проблему, вам нужно решить, какой у вас наиболее распространенный вариант использования. Если вы хотите продолжать ленивую выборку по умолчанию, вы можете локально изменить стратегию выборки, когда вам нужно: A.findAllByUser(user, [fetch: join]) .

Если, с другой стороны, вы хотите сделать быструю выборку значения по умолчанию, но хотите отключить его локально, я считаю, что вам следует использовать lazy: false вместо fetch: join в вашем классе домена, потому что это безопаснее с ассоциациями «один ко многим». И вы должны иметь возможность отключить его для любого заданного запроса (например A.findAllByUser(user, [lazy: true]) .

Смотрите здесь .