如何在JDBC中使用Mysql行构造函数进行查询?

How to query using Mysql Row Constructors in JDBC?

以下 MySQL 个查询是等价的:

select * from TableA where (column1, column2) in ( ('name1', 60), ('name2', 65) )
select * from TableA where (column1='name1' and column2=60) or (column1='name2' and column2=65)

但是,行构造函数表单(即第一个示例)的强大之处在于您可以使用它来处理查询任意长度的值对列表。没有它你必须写动态 sql 这是一个安全风险。使用第一种形式可以避免这个讨厌的问题。

但是,您如何使用准备好的语句在 JDBC 中表示这一点?例如:

Connection connection = ...
PreparedStatement smt = connection.preparedStatement("select * from TableA where (column1,column2) in ?");
smt.setObject(1, whatDataTypeGoesHere );
smt.execute();

我查看了 setArray,但是如何在数组的值中表示 column1column2 值?我想知道 SQLData 接口是否可以用作该管道。但是阅读文档我看不出它是如何工作的。

据我所知,MySQL 在 Connector/J 中的实现不支持 setArray()。它抛出 java.sql.SQLFeatureNotSupportedException.

即使它实现了 setArray(),我也没有使用过它,也没有看到任何文档显示使用该方法作为行构造函数而不是标量类型的示例。它可能不是您所拥有的任务的正确解决方案。

我想你必须写一个 string-builder-something-something 来做你想做的事。可以编写构建 SQL 查询的代码。如果您在 SQL 查询字符串中使用不受信任的内容,这只是一个 SQL 注入风险。如果只使用严格受自己代码控制的内容,可以保证不危险。

例如,在下面的示例中,插入到 SQL 字符串中的内容仅基于调用代码中的字符串文字。未使用来自不受信任来源的内容。

String placeHolders = String.join(",",
  Collections.nCopies(params.size(), "(?, ?)"));
String sql = "select * from TableA where (column1, column2) in ( (" 
  + placeHolders + ")";

(假设 params 是一个对象数组,您可以从中获取对应于 colum1 和 column2 的值。)

这将导致 SQL 字符串,例如

select * from TableA where (column1, column2) in ((?, ?), (?, ?), (?, ?), ...)

然后你必须遍历你想要绑定的参数数组,并在每个循环中设置两次 setString()