Java 使用JDBC,如何将多个ID替换为;从T中删除(?)中的id;
我有一些生成一组主键值的代码,我想从数据库表中删除这些主键值Java 使用JDBC,如何将多个ID替换为;从T中删除(?)中的id;,java,sql,jdbc,prepared-statement,Java,Sql,Jdbc,Prepared Statement,我有一些生成一组主键值的代码,我想从数据库表中删除这些主键值 long[] keysToDelete = { 0, 1, 2, 3 }; 我想用一个PreparedStatement来执行 DELETE FROM MyTable WHERE myPrimaryKey IN (0, 1, 2, 3); 知道怎么做吗?两个步骤: 使用适当的参数#构建PreparedStatement SQL字符串 在值数组上循环并将每个值绑定到其参数 不幸的是,没有一种很好的方法可以同时绑定一个数组。两个步骤:
long[] keysToDelete = { 0, 1, 2, 3 };
我想用一个PreparedStatement来执行
DELETE FROM MyTable WHERE myPrimaryKey IN (0, 1, 2, 3);
知道怎么做吗?两个步骤:
不幸的是,没有一种很好的方法可以同时绑定一个数组。不完全确定,但这可能会有所帮助:
PreparedStatement pstmt = Connection.prepareStatement("DELETE FROM MyTable WHERE myPrimaryKey IN (?)");
pstmt.setArray(1, idArray);
不完全确定,但这可能会有所帮助:
PreparedStatement pstmt = Connection.prepareStatement("DELETE FROM MyTable WHERE myPrimaryKey IN (?)");
pstmt.setArray(1, idArray);
我编写了一个类来动态生成这样的多参数查询。它目前有一些局限性(对于写作的快速性),并且还没有经过彻底的测试,但可能是一个很好的开始方法。限制:
- 仅处理一个多参数参数(?)
- 错误地将引号中的问号识别为参数
- API并不漂亮,但另一种选择是编写一个完整的PreparedStatement decorator,其中包含大量的状态管理,这比我愿意投入的工作量还要多
/**
* A PreparedStatement decorator that can bind a set of arguments
*
* A specialized ?? placeholder in a string can be bound to a set of
* values instead of just single values. Currently, only one such
* specialized placeholder is supported, and you must bind it before
* obtaining the prepared statement.
*
* If you want to bind additional values to the PreparedStatement after
* producing it, you must run the parameter index through the param()
* method.
*
* Example use:
*
*
* MultiValueBinder binder = new MultiValueBinder(
* "UPDATE table SET value = ? WHERE id IN (??)", conn);
* binder.setInts(myIds);
*
* PreparedStatement stmt = binder.statement();
* stmt.setString(binder.param(1), "myValue");
*
* ResultSet rs = stmt.executeQuery();
*
* Note: this class is not robust against using question marks in literal
* strings. Don't use them :).
*/
public class MultiValueBinder {
private Connection connection;
private PreparedStatement statement;
private String sql;
private int argumentsBefore = 0;
private int setSize = 0;
public MultiValueBinder(String sql, Connection connection) {
this.sql = sql;
this.connection = connection;
}
/**
* Bind a collection of integers to the multi-valued argument
*/
public void setInts(Collection<Integer> ints) throws SQLException {
explodeQuery(ints.size());
buildStatement();
try {
int i = 0;
for (Integer integer: ints)
statement.setInt(1 + argumentsBefore + i++, integer);
} catch (Exception ex) {
cleanStatement();
throw (ex instanceof SQLException) ? (SQLException) ex : new SQLException(ex);
}
}
/**
* Bind a collection of strings to the multi-valued argument
*/
public void setStrings(Collection<String> strings) throws SQLException {
explodeQuery(strings.size());
buildStatement();
try {
int i = 0;
for (String str: strings)
statement.setString(1 + argumentsBefore + i++, str);
} catch (Exception ex) {
cleanStatement();
throw (ex instanceof SQLException) ? (SQLException) ex : new SQLException(ex);
}
}
/**
* Explode the multi-value parameter into a sequence of comma-separated
* question marks.
*/
private void explodeQuery(int size) throws SQLException {
int mix = sql.indexOf("??");
if (mix == -1) throw new SQLException("Query does not contain a multi-valued argument.");
if (size == 0) throw new SQLException("Can't bind an empty collection; generated SQL won't parse.");
// Count the number of arguments before the multi-marker
argumentsBefore = 0;
for (int i = 0; i < mix; i++) {
if (sql.charAt(i) == '?') argumentsBefore++;
}
setSize = size;
// Generate the exploded SQL query
StringBuilder sb = new StringBuilder(sql.substring(0, mix)); // Start
for (int i = 0; i < setSize; i++) { // ?, ?, ...
if (i > 0) sb.append(", ");
sb.append('?');
}
sb.append(sql.substring(mix + 2)); // Remainder
sql = sb.toString();
}
/**
* Create the statement if it hasn't been created yet
*/
private void buildStatement() throws SQLException {
if (statement != null) return;
if (sql.contains("??"))
throw new SQLException("Multi-valued argument not bound yet.");
statement = connection.prepareStatement(sql);
}
private void cleanStatement() {
if (statement != null) {
try {
statement.close();
} catch (Exception ex) {
/* Ignore */
}
statement = null;
}
}
public PreparedStatement statement() throws SQLException {
buildStatement();
return statement;
}
/**
* Transform the 1-based-index of the given argument before query expansion
* into the index after expansion.
*
* The ?? placeholder takes up one index slot.
*/
public int param(int ix) {
if (ix <= argumentsBefore) return ix;
if (ix == argumentsBefore + 1)
throw new RuntimeException(ix + " is the index of the multi-valued parameter.");
return argumentsBefore + 1 + setSize;
}
}
/**
*可以绑定一组参数的PreparedStatement decorator
*
*专门的??字符串中的占位符可以绑定到一组
*值,而不仅仅是单个值。目前,只有一家这样的公司
*支持专用占位符,必须先绑定它
*获取准备好的报表。
*
*如果要在之后将其他值绑定到PreparedStatement
*生成它时,必须通过param()运行参数索引
*方法。
*
*示例用法:
*
*
*多值活页夹=新的多值活页夹(
*“更新表集值=?其中id位于(??),conn);
*binder.setInts(myid);
*
*PreparedStatement stmt=binder.statement();
*stmt.setString(活页夹参数(1),“myValue”);
*
*ResultSet rs=stmt.executeQuery();
*
*注意:这个类不适合在文本中使用问号
*字符串。不要使用它们:)。
*/
公共类多值绑定器{
专用连接;
私人编制的报表;
私有字符串sql;
private int argumentsBefore=0;
私有int setSize=0;
公共多值绑定器(字符串sql、连接){
this.sql=sql;
这个连接=连接;
}
/**
*将整数集合绑定到多值参数
*/
公共void setInts(集合ints)引发SQLException{
explodeQuery(ints.size());
buildStatement();
试一试{
int i=0;
用于(整数:整数)
语句.setInt(1+argumentsBefore+i++,整数);
}捕获(例外情况除外){
cleanStatement();
抛出(ex instanceof SQLException)?(SQLException)ex:new SQLException(ex);
}
}
/**
*将字符串集合绑定到多值参数
*/
公共void集合字符串(集合字符串)引发SQLException{
explodeQuery(strings.size());
buildStatement();
试一试{
int i=0;
for(字符串str:strings)
statement.setString(1+argumentsBefore+i++,str);
}捕获(例外情况除外){
cleanStatement();
抛出(ex instanceof SQLException)?(SQLException)ex:new SQLException(ex);
}
}
/**
*将多值参数分解为逗号分隔的序列
*问号。
*/
私有查询(整型大小)引发SQLException{
int mix=sql.indexOf(“??”);
如果(mix==-1)抛出新的SQLException(“查询不包含多值参数”);
如果(size==0)抛出新的SQLException(“无法绑定空集合;生成的SQL不会解析”);
//计算多重标记之前的参数数
argumentsBefore=0;
对于(int i=0;i0)sb.追加(“,”);
某人附加(“?”);
}
sb.append(sql.substring(mix+2));//余数
sql=sb.toString();
}
/**
*如果尚未创建语句,请创建该语句
*/
私有void buildStatement()引发SQLException{
if(statement!=null)返回;
if(sql.contains(“??”)
抛出新的SQLException(“多值参数尚未绑定”);
语句=connection.prepareStatement(sql);
}
私有语句(){
if(语句!=null){
试一试{
语句。close();
}捕获(例外情况除外){
/*忽略*/
}
语句=null;
}
}
公共PreparedStatement语句()引发SQLException{
buildStatement();
返回语句;
}
/**
*在查询扩展之前,转换给定参数的基于1的索引
*扩展后进入索引。
*
*?占位符占用一个索引槽。
*/
公共int参数(int ix){
if(ix我已经编写了一个类来动态生成这样一个多参数查询。它目前有一些限制(为了编写的快速性),还没有经过彻底的测试,但可能是一个很好的入门方法。限制: