如何用GORM查询仅含指定枚举值的hasMany关联Domain实例
Grails GORM查询:筛选flags仅包含OTHER_VALUE的Domain实例
场景与代码示例
开发Grails应用时,Domain类与Flags枚举存在hasMany关联,简化代码如下:
class Domain { static hasMany = [ flags: Flags ] } enum Flags { VALUE, OTHER_VALUE }
需要编写GORM查询,找出flags集合仅包含OTHER_VALUE枚举值的所有Domain实例,之前尝试的写法无法正常工作:
Domain.where { flags.contains(Flag.VALUE) // 存在枚举类名称拼写错误:应为Flags而非Flag }.list()
问题
- 如何正确构建该GORM查询?
- 处理GORM中枚举的hasMany关联是否有特殊方式?
解答
1. 正确构建查询
要筛选出flags仅包含OTHER_VALUE的Domain实例,需要同时满足两个条件:包含OTHER_VALUE且不包含任何其他枚举值(如VALUE),以下是两种可行写法:
方式一:使用GORM动态查询(where语法)
Domain.where { flags.contains(Flags.OTHER_VALUE) && !flags.contains(Flags.VALUE) }.list()
方式二:使用HQL查询
如果需要更复杂的逻辑,HQL写法会更灵活:
Domain.executeQuery(""" SELECT d FROM Domain d WHERE EXISTS ( SELECT 1 FROM d.flags f WHERE f = :otherValue ) AND NOT EXISTS ( SELECT 1 FROM d.flags f2 WHERE f2 = :value ) """, [otherValue: Flags.OTHER_VALUE, value: Flags.VALUE])
注:你之前的查询失败还有一个关键原因——枚举类名称拼写错误:代码里写了
Flag.VALUE,但实际枚举类是Flags,修正拼写后基础的contains查询才能正常工作。
2. 枚举hasMany关联的特殊处理
GORM对枚举的hasMany关联处理和普通实体类的hasMany基本一致,但有几点需要注意:
- 存储映射:GORM默认会在关联表中存储枚举的名称字符串,也可以通过映射配置改为存储ordinal值:
class Domain { static hasMany = [flags: Flags] static mapping = { flags enumType: 'ordinal' // 可选值:'string'(默认)或 'ordinal' } } - 查询简化:查询时直接使用枚举实例即可,GORM会自动完成枚举与数据库存储值的转换,无需手动处理字符串/数字转换。
- 避免拼写错误:枚举类名称、枚举值的拼写必须完全匹配,否则会导致查询失败或语法错误。
内容的提问来源于stack exchange,提问作者Ev0oD
相关产品推荐
相关产品推荐

