Я работаю с приложением Grails, в котором у меня есть доменный класс, который имеет связь hasMany с перечислением. Вот упрощенная версия кода:
class Domain {
static hasMany = [
flags: Flags
]
}
enum Flags {
VALUE, OTHER_VALUE
}
Мне нужно написать запрос GORM, который находит все экземпляры Domain, в которых коллекция flags содержит только значение перечисления OTHER_VALUE.
Как я могу правильно сформулировать запрос GORM, который возвращает экземпляры Domain, в которых коллекция flags содержит только перечисление OTHER_VALUE?
Есть ли в GORM особый способ обработки отношений hasMany с перечислениями, который мне не хватает?
Ищу что-то вроде
Domain.where {
flags.contains(Flag.VALUE)
}.list()
однако вышеизложенное не является нормой.
Эй, «содержит» на самом деле не работает, это была одна из вещей, которые я пробовал, как показано в вопросе. Что касается вашего предложения 1. оно не работает, я только что попробовал 2. даже если бы оно сработало, это было бы проблематично, потому что в нашем реальном случае с продом может быть много флагов, и мне нужно проверить наличие одного, а не проверка равенства всего набора.





Сначала я думал, что 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. Связаны ли вы каким-либо образом с этой технологией, или все еще есть какая-то надежда на то, что для этого существует подход более высокого уровня, о котором мы просто не знаем?
Я использую GORM около 10 лет. Я не участвую в этом. Хотя сам запрос прост, он сложен с точки зрения ORM, поскольку требует сочетания группировки, агрегации и фильтрации коллекции. Вот почему у GORM нет простого высокоуровневого метода для этого конкретного сценария, не прибегающего к использованию SQL. Явно сопоставляя таблицу флагов, вы можете использовать несколько других параметров, таких как критерии GORM и HQL. Некоторые ORM имеют выразительный синтаксис, подобный SQL, для обработки этого. Но на этом этапе вы в основном пишете SQL, а не абстрактно.
Спасибо большое за контекст, вы помогли нам принять решение, как двигаться дальше. Это также наталкивает на мысль о том, что вместо этого мы введем простой класс предметной области, который будет содержать только это перечисление, чтобы реализовать его как настоящую ассоциацию двух объектов предметной области по принципу «один ко многим». Просто мысль. Если бы это означало значительно меньшую производительность, sql мог бы работать. Что мне не нравится в sql, так это то, что его сложнее поддерживать в случае некоторых переименований и тому подобного. Однако это случается нечасто, так что, возможно, это нормально.
Сейчас у меня нет возможности протестировать это, поэтому просто добавляю в качестве комментария. Разве не получилось бы сделать что-то вроде
Domain.where { flags == [Flag.VALUE]) }? Вы также можете проверить, что размер == 1 и содержит VALUE, но это кажется немного хакерским.