如何在Groovy SQL中读取每行?解决MachineName属性不存在报错
解决Groovy sql.eachRow静态类型检查错误:No such property: MachineName for class: java.lang.Object
这个问题其实是两个点导致的:一是代码里的语法错误,二是Groovy静态类型检查的限制。咱们一步步来解决:
1. 先修复明显的语法错误
你在eachRow方法的参数传递上括号配对出错了,SQL语句和参数Map的位置没放对。正确的eachRow调用格式应该是把SQL字符串作为第一个参数,参数Map作为第二个参数,再跟上处理行的闭包。
2. 解决静态类型检查的限制
当Groovy开启静态类型检查(比如使用@CompileStatic注解)时,闭包里的row对象会被默认推断为Object类型,静态检查器不知道它有MachineName这个属性,所以会抛出"No such property"的错误。针对这个问题,有几种常用的解决方式:
方式一:使用下标访问列
用row["列名"]的方式访问,这种写法能被静态检查器识别,避免属性不存在的错误:
// 修正后的完整代码示例 sql.eachRow('select * from [MACHINES] WHERE UpdateTime > :lastTimeRead', [lastTimeRead: Long.parseLong(lastTimeRead)]) { row -> def read = row["MachineName"] }
方式二:明确指定row的类型
如果你的代码开启了@CompileStatic,可以把闭包里的row类型指定为GroovyResultSet(Groovy对JDBC ResultSet的包装类),这样静态检查器就能识别列属性:
@CompileStatic def loadMachines(Sql sql, String lastTimeRead) { sql.eachRow('select * from [MACHINES] WHERE UpdateTime > :lastTimeRead', [lastTimeRead: Long.parseLong(lastTimeRead)]) { GroovyResultSet row -> def read = row.MachineName } }
方式三:使用getAt方法
和下标访问等价,调用row.getAt("MachineName")也能绕过静态检查的限制:
def machineName = row.getAt("MachineName")
方式四:临时关闭静态检查(不推荐,除非必要)
如果只是这一段代码有问题,可以给闭包或者方法加上@SuppressWarnings("GroovyAssignabilityCheck")注解,临时关闭该部分的静态类型检查:
@SuppressWarnings("GroovyAssignabilityCheck") sql.eachRow('select * from [MACHINES] WHERE UpdateTime > :lastTimeRead', [lastTimeRead: Long.parseLong(lastTimeRead)]) { row -> def read = row.MachineName }
总结
先修正语法错误,再根据是否开启静态类型检查选择对应的列访问方式,就能解决这个错误了。
内容的提问来源于stack exchange,提问作者user9630935
相关产品推荐
相关产品推荐

