Как запросить домен GORM с помощью отношения перечисления hasMany, чтобы найти записи, содержащие только определенные значения Enum?

Я работаю с приложением Grails, в котором у меня есть доменный класс, который имеет связь hasMany с перечислением. Вот упрощенная версия кода:

class Domain {
    static hasMany = [
        flags: Flags
    ]
}

enum Flags {
    VALUE, OTHER_VALUE
}

Мне нужно написать запрос GORM, который находит все экземпляры Domain, в которых коллекция flags содержит только значение перечисления OTHER_VALUE.

  1. Как я могу правильно сформулировать запрос GORM, который возвращает экземпляры Domain, в которых коллекция flags содержит только перечисление OTHER_VALUE?

  2. Есть ли в GORM особый способ обработки отношений hasMany с перечислениями, который мне не хватает?

Ищу что-то вроде

Domain.where {
   flags.contains(Flag.VALUE)
}.list()

однако вышеизложенное не является нормой.

Сейчас у меня нет возможности протестировать это, поэтому просто добавляю в качестве комментария. Разве не получилось бы сделать что-то вроде Domain.where { flags == [Flag.VALUE]) }? Вы также можете проверить, что размер == 1 и содержит VALUE, но это кажется немного хакерским.

Daniel 12.08.2024 18:25

Эй, «содержит» на самом деле не работает, это была одна из вещей, которые я пробовал, как показано в вопросе. Что касается вашего предложения 1. оно не работает, я только что попробовал 2. даже если бы оно сработало, это было бы проблематично, потому что в нашем реальном случае с продом может быть много флагов, и мне нужно проверить наличие одного, а не проверка равенства всего набора.

Ev0oD 13.08.2024 21:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сначала я думал, что HQL будет простым ответом на этот вопрос, но после того, как вы попробуете, в зависимости от текущих настроек вашего домена вы получите ошибки несопоставленной таблицы, поскольку DOMAIN_FLAGS фактически не определен.

Вместо этого я решил создать собственный оператор SQL. Это метод, к которому я пришел. Вам понадобится внедренный sessionFactory.

List<Domain> sqlQuery() {
    def session = sessionFactory.currentSession
    def sql = """select d.* from domain d
        where d.id in (
            select domain_id from DOMAIN_FLAGS
            group by domain_id
            having count(*) = 1 and max(flags) = 'OTHER_VALUE'
        )"""

    session.createSQLQuery(sql)
            .setParameter('flag', Flags.OTHER_VALUE.toString())
            .addEntity(Domain)
            .list()
}

Большое спасибо за ваш ответ. Да, я знал, что могу прибегнуть к прямым операторам sql. Однако я подумал, что было бы очень странно, что такая простая вещь для запроса не будет поддерживаться и потребует прямого sql. Связаны ли вы каким-либо образом с этой технологией, или все еще есть какая-то надежда на то, что для этого существует подход более высокого уровня, о котором мы просто не знаем?

Ev0oD 13.08.2024 21:02

Я использую GORM около 10 лет. Я не участвую в этом. Хотя сам запрос прост, он сложен с точки зрения ORM, поскольку требует сочетания группировки, агрегации и фильтрации коллекции. Вот почему у GORM нет простого высокоуровневого метода для этого конкретного сценария, не прибегающего к использованию SQL. Явно сопоставляя таблицу флагов, вы можете использовать несколько других параметров, таких как критерии GORM и HQL. Некоторые ORM имеют выразительный синтаксис, подобный SQL, для обработки этого. Но на этом этапе вы в основном пишете SQL, а не абстрактно.

RetroRoot 14.08.2024 12:34

Спасибо большое за контекст, вы помогли нам принять решение, как двигаться дальше. Это также наталкивает на мысль о том, что вместо этого мы введем простой класс предметной области, который будет содержать только это перечисление, чтобы реализовать его как настоящую ассоциацию двух объектов предметной области по принципу «один ко многим». Просто мысль. Если бы это означало значительно меньшую производительность, sql мог бы работать. Что мне не нравится в sql, так это то, что его сложнее поддерживать в случае некоторых переименований и тому подобного. Однако это случается нечасто, так что, возможно, это нормально.

Ev0oD 15.08.2024 14:18

Другие вопросы по теме