Vert.x PgClient预查询传参错误:参数数量不匹配问题排查
问题分析与解决方案
咱们一步一步拆解问题根源,再给出修复方案:
核心问题1:根本没传递参数给查询
你看业务层代码里的execute(ar -> {...}),这个方法调用完全没传入任何参数!Vert.x的preparedQuery执行时,必须把参数通过execute方法传进去,不然数据库收到的查询就没有参数值,自然会报错“实际参数数量为0”。
核心问题2:SQL里的$3、$4被当成了字符串字面量
你的SQL语句中,substring(art.codigobarra,1,2) = '$3'这里的'$3'是带单引号的,PostgreSQL会把它当作固定字符串$3,而不是参数占位符。所以数据库只能识别到$1和$2两个有效占位符,这就是报错里“预期参数数量为2”的原因。
修复步骤
1. 修正SQL语句
去掉$3、$4外面的单引号,让它们成为真正的参数占位符:
private static final String SELECT_CBA = "select art.leyenda, $1::numeric(10,3) as cantidad, uni.abreviatura, \r" + "round(((art.precio_costo * (art.utilidad_fraccionado/100)) + art.precio_costo) * $2::numeric(10,3),2) as totpagar \r" + "FROM public.articulos art join public.unidades uni on uni.idunidad = art.idunidad \r" + "WHERE (substring(art.codigobarra,1,2) = $3 and substring(art.codigobarra,3,6) = $4)";
2. 补全参数传递与类型转换
从路由中提取参数,转换成SQL需要的类型,再传递给execute方法:
public void getOneReadingBarcode(RoutingContext routingContext) { HttpServerResponse response = routingContext.response(); // 从路由路径中提取参数 String cantComp1Str = routingContext.pathParam("cantcomp1"); String cantComp2Str = routingContext.pathParam("cantcomp2"); String tipoProd = routingContext.pathParam("tipoprod"); String prodPadre = routingContext.pathParam("prodpadre"); // 把字符串参数转成数值类型($1、$2需要numeric,这里用Double示例,建议用BigDecimal处理精确数值) try { Double cantComp1 = Double.parseDouble(cantComp1Str); Double cantComp2 = Double.parseDouble(cantComp2Str); // 按SQL占位符顺序组装参数 Tuple params = Tuple.of(cantComp1, cantComp2, tipoProd, prodPadre); pgClient .preparedQuery(SELECT_CBA) .execute(params, ar -> { if (ar.succeeded()) { RowSet<Row> rows = ar.result(); if (!rows.isEmpty()) { Row row = rows.iterator().next(); JsonObject result = new JsonObject() .put("leyenda", row.getString("leyenda")) .put("cantidad", row.getDouble("cantidad")) .put("abreviatura", row.getString("abreviatura")) .put("totpagar", row.getDouble("totpagar")); response.putHeader("Content-Type", "application/json") .end(result.encode()); } else { response.setStatusCode(404) .end("未找到匹配的商品"); } } else { response.setStatusCode(500) .end("查询失败: " + ar.cause().getMessage()); } }); } catch (NumberFormatException e) { // 处理参数格式错误 response.setStatusCode(400) .end("数值参数格式错误: " + e.getMessage()); } }
为什么这样修复?
- 去掉单引号后,PostgreSQL会正确识别4个参数占位符,和你传入的4个参数一一对应;
- 传递参数后,PgClient会自动处理字符串类型的转义与引号包裹,避免SQL注入风险;
- 类型转换确保了参数和SQL定义的
numeric类型匹配,不会出现类型不兼容的问题。
内容的提问来源于stack exchange,提问作者Ernesto Andres Zapata Icart
相关产品推荐
相关产品推荐

