使用JDBC参数化IN子句的最佳方法是什么?

使用JDBC参数化IN子句的最佳方法是什么?

假设我有一个表单查询

SELECT * FROM MYTABLE WHERE MYCOL in (?)

我想参数化参数。

有没有一种直接的方法在Java中使用JDBC,以一种可以在不修改SQL本身的情况下在多个数据库上工作的方式?

我发现的最接近的问题与C#有关,我想知道Java / JDBC是否有不同之处。


莫回无
浏览 2921回答 3
3回答

森林海

在JDBC中确实没有直接的方法来做到这一点。一些&nbsp;JDBC驱动程序似乎支持PreparedStatement#setArray()该IN子句。我只是不确定那是哪一个。你可以使用helper方法String#join()和Collections#nCopies()to生成占位符for&nbsp;IN子句和另一个helper方法来设置循环中的所有值PreparedStatement#setObject()。public&nbsp;static&nbsp;String&nbsp;preparePlaceHolders(int&nbsp;length)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;String.join(",",&nbsp;Collections.nCopies(length,&nbsp;"?"));}public&nbsp;static&nbsp;void&nbsp;setValues(PreparedStatement&nbsp;preparedStatement,&nbsp;Object...&nbsp;values)&nbsp;throws&nbsp;SQLException&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;values.length;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preparedStatement.setObject(i&nbsp;+&nbsp;1,&nbsp;values[i]); &nbsp;&nbsp;&nbsp;&nbsp;}}以下是您可以使用它的方法:private&nbsp;static&nbsp;final&nbsp;String&nbsp;SQL_FIND&nbsp;=&nbsp;"SELECT&nbsp;id,&nbsp;name,&nbsp;value&nbsp;FROM&nbsp;entity&nbsp;WHERE&nbsp;id&nbsp;IN&nbsp;(%s)";public&nbsp;List<Entity>&nbsp;find(Set<Long>&nbsp;ids)&nbsp;throws&nbsp;SQLException&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;List<Entity>&nbsp;entities&nbsp;=&nbsp;new&nbsp;ArrayList<Entity>(); &nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sql&nbsp;=&nbsp;String.format(SQL_FIND,&nbsp;preparePlaceHolders(ids.size())); &nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;connection&nbsp;=&nbsp;dataSource.getConnection(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PreparedStatement&nbsp;statement&nbsp;=&nbsp;connection.prepareStatement(sql); &nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setValues(statement,&nbsp;ids.toArray()); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;(ResultSet&nbsp;resultSet&nbsp;=&nbsp;statement.executeQuery())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(resultSet.next())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entities.add(map(resultSet)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;entities;}private&nbsp;static&nbsp;Entity&nbsp;map(ResultSet&nbsp;resultSet)&nbsp;throws&nbsp;SQLException&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Enitity&nbsp;entity&nbsp;=&nbsp;new&nbsp;Entity(); &nbsp;&nbsp;&nbsp;&nbsp;entity.setId(resultSet.getLong("id")); &nbsp;&nbsp;&nbsp;&nbsp;entity.setName(resultSet.getString("name")); &nbsp;&nbsp;&nbsp;&nbsp;entity.setValue(resultSet.getInt("value")); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;entity;}请注意,某些数据库在IN子句中具有允许的值限制。例如,Oracle对1000个项目有此限制。

郎朗坤

既然没有人回答大型IN子句(超过100个)的情况,我会把我的解决方案抛给这个适用于JDBC的问题。简而言之,我用tmp表替换了INa&nbsp;INNER JOIN。我所做的是制作我称之为批处理ids表的内容,根据RDBMS,我可以将其设为tmp表或内存表。该表有两列。一列具有来自IN子句的id,另一列具有我在运行中生成的批次ID。SELECT&nbsp;*&nbsp;FROM&nbsp;MYTABLE&nbsp;M&nbsp;INNER&nbsp;JOIN&nbsp;IDTABLE&nbsp;T&nbsp;ON&nbsp;T.MYCOL&nbsp;=&nbsp;M.MYCOL&nbsp;WHERE&nbsp;T.BATCH&nbsp;=&nbsp;?在您选择之前,将您的ID推送到具有给定批次ID的表中。然后,您只需将原始查询IN子句替换为ID表上的INNER JOIN匹配WHERE batch_id等于当前批次。完成后,删除批量条目。

慕桂英546537

执行此操作的标准方法是(如果您使用的是Spring JDBC)是使用org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate类。使用此类,可以将List定义为SQL参数,并使用NamedParameterJdbcTemplate替换命名参数。例如:public&nbsp;List<MyObject>&nbsp;getDatabaseObjects(List<String>&nbsp;params)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;NamedParameterJdbcTemplate&nbsp;jdbcTemplate&nbsp;=&nbsp;new&nbsp;NamedParameterJdbcTemplate(dataSource); &nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sql&nbsp;=&nbsp;"select&nbsp;*&nbsp;from&nbsp;my_table&nbsp;where&nbsp;my_col&nbsp;in&nbsp;(:params)"; &nbsp;&nbsp;&nbsp;&nbsp;List<MyObject>&nbsp;result&nbsp;=&nbsp;jdbcTemplate.query(sql,&nbsp;Collections.singletonMap("params",&nbsp;params),&nbsp;myRowMapper); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result;}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java