AWS Athena JDBC驱动PreparedStatement绑定变量失败问题求助
我之前踩过完全一样的坑!用Simba的Athena JDBC 2.0.2版本时,PreparedStatement带?占位符就报参数不匹配,直接硬写值却没问题,这个报错的根源是早期版本的Athena JDBC驱动对PreparedStatement的实现有缺陷。
问题原因
Athena JDBC驱动2.0.2版本在创建PreparedStatement的阶段,就会把带?占位符的SQL直接发送给Athena服务做语法校验,但这时候你还没调用setInt()这类方法设置参数,Athena自然会认为你少传了参数,抛出「预期1个参数但实际找到0个」的错误。而正常的JDBC驱动应该是先创建PreparedStatement对象,等你设置完参数后,再把参数化的请求发送给数据库。
解决方案
有两个可行的解决办法,优先选第一个:
升级JDBC驱动版本
Simba在后续的版本(比如2.0.3及以上,更推荐直接用最新的3.x系列)修复了这个PreparedStatement的bug。你只需要替换掉旧的AthenaJDBC42_2.0.2.jar,使用最新版驱动,你的测试代码testWhichFails()就能直接正常运行,不需要改任何业务代码。临时启用客户端模拟PreparedStatement(不推荐长期用)
如果暂时没法升级驱动,可以在JDBC连接URL里添加UsePreparedStatement=true参数,让驱动在客户端这边把占位符替换成实际参数后,再发送给Athena。比如你的连接URL可以改成:jdbc:awsathena://AwsRegion=你的区域;S3OutputLocation=s3://你的输出桶路径/;UsePreparedStatement=true注意:这个方法是客户端侧的模拟,相当于把参数直接拼进SQL里,存在SQL注入的风险,所以只适合临时应急,还是尽快升级驱动更稳妥。
为什么硬写值的测试能正常运行?
因为testWhichWorks()里的SQL是完整的,没有占位符,驱动直接把完整的SQL发送给Athena,Athena能正常解析执行,不需要做参数校验,所以不会报错。
内容的提问来源于stack exchange,提问作者Comencau

