只有上次更新查询在 JAVA 的 addBatch 中有效
Only Last Update query working in addBatch of JAVA
我正在使用以下代码
con.setAutoCommit(false);
for(int i=0;i<requestBody.size();i++)
{
bulk_Update_Qry = new StringBuffer();
if (requestBody.getUserDetails().get(i).getFirstName() != null)
dbutil.setField(bulk_Update_Qry, "FIRST_NAME",requestBody.getUserDetails().get(i).getFirstName());
if (requestBody.getUserDetails().get(i).getLastName() != null)
dbutil.setField(bulk_Update_Qry, "LAST_NAME",requestBody.getUserDetails().get(i).getLastName());
if (requestBody.getUserDetails().get(i).getPhone() != null)
dbutil.setField(bulk_Update_Qry, "PHONE",requestBody.getUserDetails().get(i).getPhone() );
if (requestBody.getUserDetails().get(i).getEmail() != null)
dbutil.setField(bulk_Update_Qry, "EMAIL",requestBody.getUserDetails().get(i).getEmail());
if (requestBody.getUserDetails().get(i).getAddress()!= null)
dbutil.setField(bulk_Update_Qry, "ADDRESS",requestBody.getUserDetails().get(i).getAddress());
if (requestBody.getUserDetails().get(i).getZip() != null)
dbutil.setField(bulk_Update_Qry, "ZIP",requestBody.getUserDetails().get(i).getZip() );
if (requestBody.getUserDetails().get(i).getCity() != null)
dbutil.setField(bulk_Update_Qry, "CITY",requestBody.getUserDetails().get(i).getCity() );
if (requestBody.getUserDetails().get(i).getState() != null)
dbutil.setField(bulk_Update_Qry, "STATE",requestBody.getUserDetails().get(i).getState());
if (requestBody.getUserDetails().get(i).getCountry() != null)
dbutil.setField(bulk_Update_Qry, "COUNTRY",requestBody.getUserDetails().get(i).getCountry());
System.out.println("UPDATE CINR_USER SET " + bulk_Update_Qry + " WHERE ID = \'" + requestBody.getUserDetails().get(i).getId() + "\'");
ps = con.prepareStatement("UPDATE CINR_USER SET " + bulk_Update_Qry + " WHERE ID = \'" + requestBody.getUserDetails().get(i).getId() + "\'");
ps.addBatch();
}
ps.executeBatch();
con.commit();
这是一个动态更新查询。
setField
是我定义的一个函数,用于验证它是否存在于请求中。
我面临的问题
如果有5个更新查询,则只执行第5个查询。我不确定前四个查询发生了什么。
我也买不起
ps = con.prepareStatement(.....)
在 for 循环之外,因为我正在使用动态更新查询。
谁能澄清我做错了什么?
每次调用 prepareStatement
都会创建一个新的 PreparedStatement
对象,这显然具有清除 PreparedStatement
对象的前一个实例的批处理的效果。因此,当您最终调用 executeBatch
时,它只包含循环最后一次迭代的单个条目。
因此,如果您需要为每次迭代执行不同的 PreparedStatement
,您需要调用 executeUpdate
而不是 addBatch
(并省略 executeBatch
调用).由于您正在(ab)使用 PreparedStatement
执行动态 SQL,您 可以 使用简单的 Statement
并调用 addBatch(sql)
,但是强烈建议不要使用动态 SQL,因为它会打开您的代码 SQL 注入漏洞。
在每个循环中,您都在创建一个新的 PreparedStatement
对象,并且批处理是 每个语句对象 。换句话说,每次循环你扔掉前一个循环的批处理,最后你有一个准备好的语句,它有一个只包含一个语句的批处理,所以你只执行定义在最后的 运行 中的语句循环。
有几种方法可以解决这个问题:
- 使用在循环外创建的普通
Statement
对象。
这会起作用,因为您实际上并没有使用准备好的语句的主要功能,但这也是不安全的。您当前构建语句的方式使您对 SQL 注入敞开大门。
- 不要尝试使用批处理,只执行循环内的语句。
但在执行此操作之前,您需要齐心协力并正确参数化您的查询。
- 在循环之前定义多个带有正确参数化查询的准备语句,并向正确的语句添加一个批处理,在循环之后执行所有这些查询。
我正在使用以下代码
con.setAutoCommit(false);
for(int i=0;i<requestBody.size();i++)
{
bulk_Update_Qry = new StringBuffer();
if (requestBody.getUserDetails().get(i).getFirstName() != null)
dbutil.setField(bulk_Update_Qry, "FIRST_NAME",requestBody.getUserDetails().get(i).getFirstName());
if (requestBody.getUserDetails().get(i).getLastName() != null)
dbutil.setField(bulk_Update_Qry, "LAST_NAME",requestBody.getUserDetails().get(i).getLastName());
if (requestBody.getUserDetails().get(i).getPhone() != null)
dbutil.setField(bulk_Update_Qry, "PHONE",requestBody.getUserDetails().get(i).getPhone() );
if (requestBody.getUserDetails().get(i).getEmail() != null)
dbutil.setField(bulk_Update_Qry, "EMAIL",requestBody.getUserDetails().get(i).getEmail());
if (requestBody.getUserDetails().get(i).getAddress()!= null)
dbutil.setField(bulk_Update_Qry, "ADDRESS",requestBody.getUserDetails().get(i).getAddress());
if (requestBody.getUserDetails().get(i).getZip() != null)
dbutil.setField(bulk_Update_Qry, "ZIP",requestBody.getUserDetails().get(i).getZip() );
if (requestBody.getUserDetails().get(i).getCity() != null)
dbutil.setField(bulk_Update_Qry, "CITY",requestBody.getUserDetails().get(i).getCity() );
if (requestBody.getUserDetails().get(i).getState() != null)
dbutil.setField(bulk_Update_Qry, "STATE",requestBody.getUserDetails().get(i).getState());
if (requestBody.getUserDetails().get(i).getCountry() != null)
dbutil.setField(bulk_Update_Qry, "COUNTRY",requestBody.getUserDetails().get(i).getCountry());
System.out.println("UPDATE CINR_USER SET " + bulk_Update_Qry + " WHERE ID = \'" + requestBody.getUserDetails().get(i).getId() + "\'");
ps = con.prepareStatement("UPDATE CINR_USER SET " + bulk_Update_Qry + " WHERE ID = \'" + requestBody.getUserDetails().get(i).getId() + "\'");
ps.addBatch();
}
ps.executeBatch();
con.commit();
这是一个动态更新查询。
setField
是我定义的一个函数,用于验证它是否存在于请求中。
我面临的问题
如果有5个更新查询,则只执行第5个查询。我不确定前四个查询发生了什么。
我也买不起
ps = con.prepareStatement(.....)
在 for 循环之外,因为我正在使用动态更新查询。
谁能澄清我做错了什么?
每次调用 prepareStatement
都会创建一个新的 PreparedStatement
对象,这显然具有清除 PreparedStatement
对象的前一个实例的批处理的效果。因此,当您最终调用 executeBatch
时,它只包含循环最后一次迭代的单个条目。
因此,如果您需要为每次迭代执行不同的 PreparedStatement
,您需要调用 executeUpdate
而不是 addBatch
(并省略 executeBatch
调用).由于您正在(ab)使用 PreparedStatement
执行动态 SQL,您 可以 使用简单的 Statement
并调用 addBatch(sql)
,但是强烈建议不要使用动态 SQL,因为它会打开您的代码 SQL 注入漏洞。
在每个循环中,您都在创建一个新的 PreparedStatement
对象,并且批处理是 每个语句对象 。换句话说,每次循环你扔掉前一个循环的批处理,最后你有一个准备好的语句,它有一个只包含一个语句的批处理,所以你只执行定义在最后的 运行 中的语句循环。
有几种方法可以解决这个问题:
- 使用在循环外创建的普通
Statement
对象。
这会起作用,因为您实际上并没有使用准备好的语句的主要功能,但这也是不安全的。您当前构建语句的方式使您对 SQL 注入敞开大门。 - 不要尝试使用批处理,只执行循环内的语句。
但在执行此操作之前,您需要齐心协力并正确参数化您的查询。 - 在循环之前定义多个带有正确参数化查询的准备语句,并向正确的语句添加一个批处理,在循环之后执行所有这些查询。