Grails 3.3中GORM CriteriaBuilder如何对属性调用函数?
嘿,这个问题我之前也踩过坑!CriteriaBuilder的eq方法默认会把第一个参数当成域类的属性名,而不是SQL函数调用,所以你直接写eq 'hour(registration)', 15肯定不会生效——它会傻呵呵地去找Student里叫hour(registration)的属性,当然找不到啦😅
下面给你两种不用改域类映射的优雅解决方案:
方法1:用GORM自带的function() API(优先推荐)
Grails 3.3的GORM CriteriaBuilder其实专门提供了function()方法来调用数据库函数,完全符合DSL风格,写法如下:
def c = Student.createCriteria() def results = c.list { eq(function('hour', property('registration')), 15) }
function('hour', ...):告诉GORM你要调用数据库的hour函数property('registration'):把域类的registration字段作为函数参数传进去- 这种方式是GORM抽象层支持的,比直接写SQL更干净,要是以后换数据库(比如从MySQL转PostgreSQL),只要函数名一致就能直接用,不用改代码。
方法2:用sqlRestriction写原生SQL片段
如果需要更复杂的SQL逻辑,或者数据库函数名比较特殊,可以直接用sqlRestriction注入原生过滤条件:
def c = Student.createCriteria() def results = c.list { sqlRestriction "hour(registration) = ?", [15] }
- 第一个参数是SQL条件片段,
?是安全的占位符,第二个参数是对应的值(防止SQL注入) - 注意哦,不同数据库的小时提取函数可能不一样,比如Oracle要用
EXTRACT(HOUR FROM registration),所以这种方式要考虑数据库兼容性。
为啥原来的写法不行?
再给你捋清楚原因:where查询的DSL有专门的函数解析逻辑,能识别hour(registration)是函数调用;但CriteriaBuilder的eq方法默认只认属性名,它会把hour(registration)当成一个属性的名字,自然查不到任何结果啦。
内容的提问来源于stack exchange,提问作者MonetsChemist
相关产品推荐
相关产品推荐

