关闭

PrepareStatement sql语句in中多个参数的实现

标签: javapreparedstatement
2864人阅读 评论(0) 收藏 举报
分类:

下边是今天探索PrepareStatement预编译where条件为in的sql语句的过程,在mysql环境中只有第四种方法实现了,Oracle中可能第三种也可以不过没有测试,如果有需要可以直接跳转。

1.通过拼接字符串设置参数×

今天在实现一个数据库批量更新的代码时,发现

String sql = "UPDATE t_demo SET columns='Well' WHERE column_id IN (?)";

这条语句中的参数在使用PrepareStatement来预编译之后,是不可以传入一个拼接字符串的,比如

String criteria="'a','b','c'";
prepareStatement.setString(1,criteria);

想要达到的效果是和执行下边一条语句一样:

UPDATE t_demo SET columns='Well' WHERE column_id IN ('a','b','c')

但是最后发现这样并不起作用,最后思考后恍然大悟。
因为PrepareStatement是预编译的,所以在编译完sql语句后发现这个sql只有一个参数,所以在设置参数的时候会默认(’a’,’b’,’c’)为一个参数,就会去查找column_id为“’a’,’b’,’c’”的数据,结果当然是不符合期望的。

2. 通过Vector设置参数×

这个是网上找到的一个方法,我的用法如下,但是最后使用后发现也是不起作用的,但是也没有报错。不知道是不是我的问题。不过还是贴上来代码供大家研究

String arr[]={"a","b","c"};
Vector v=new Vector(Arrays.asList(arr));
prepareStatement.setObject(1,v);
prepareStatement.executeUpdate();

3. 通过PrepareStatement的setArray()方法

这个也是在网上发现的方法,这个是不支持mysql数据库的,在mysql环境下使用会报SQLFeatureNotSupportedException异常
可能支持Oracle(没有测试)。
代码如下。

String arr[]={"a","b","c"};
Array v=conn.createArrayOf("VARCHAR", arr);
prepareStatement.setArray(1, v);
prepareStatement.executeUpdate();

4. 设置多个参数√

上边几个方法都在我的mysql环境中阵亡了之后,就只好使用笨方法了。那就是在in的条件中多加几个“?”。
因为我这次任务处理的数据比较多达8w多条,所以我分批处理。代码如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;

public class Test {

    static String url = ...;
    static String user = ...;
    static String password =...;

    static String sql = "UPDATE t_demo SET columns='Well' WHERE column_id IN (_SQL)";

    static int NUM=100;

    public static void main(String[] args) throws SQLException {

        // 下边为条件,因为数据太多存在文件中
        // 读取文件然后通过字符串的split方法转为数组
        // TestChange是自己写的一个读文件并转为字符串的类,由于不是重点所以就不上代码了

        String content = TestChange.readString3("D:/demo.txt");
        String pNo[] = content.split(",");

        // 设置根据参数多少多少设置sql
        setSql();

        Connection conn = null;
        PreparedStatement stmt=null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(url, user, password);
            conn.setAutoCommit(false);
            stmt = conn.prepareStatement(sql);
            // 分批处理数组中的数据
            for (int begin = 0; begin < pNo.length; begin += NUM) {
                Date beginTime=new Date();
                int end=(begin>(pNo.length-NUM)?pNo.length:(begin+NUM));
                String arr[]=(String[])Arrays.copyOfRange(pNo, begin, end);

                // 循环设置参数
                int flag=1;
                for (String criteria: arr) {
                    if(flag ==1)
                        System.out.print("First:"+criteria+",");
                    if(flag ==arr.length)
                        System.out.println("Last:"+criteria);

                    stmt.setString(flag, criteria);
                    flag++;
                }

                int num=stmt.executeUpdate();
                Date endTime=new Date();
                Long usedTime=endTime.getTime()-beginTime.getTime();
                System.out.println("Data to be change:"+begin+"-"+end+",changed:"+num+",used time:"+usedTime);

            }
            conn.commit();
            System.out.println("Well Done!");

        } catch (Exception e) {
            e.printStackTrace();
            conn.rollback();
        }finally{
            stmt.close();
            conn.close();
        }
    }
    // 设置SQL语句,一次处理多少条数据就设置多少个“?”
    private static void setSql() {
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<NUM;++i){
            sb.append("?,");
        }
        sb.deleteCharAt(sb.lastIndexOf(","));
        sql=sql.replace("_SQL", sb.toString());
    }

}

注意:上边的代码仅说明了这种方法的思路和大致实现,但具有漏洞,NUM在执行到最后一批时还是会为100,但可能没有那么多参数需要设置。
比如我有122个数据需要update,NUM设置为100。也就是第一次设置了100个?,第二次还会继续设置100个?,但是在setString的时候后边的78个就会因为没有重新set而还会是原来的那几个,因为在我的需求中没有影响,所以没有处理,各位大佬们在参考的时候要注意
欢迎交流mail: helloleif@foxmail.com

1
0
查看评论

JDBC PreparedStatement 批量查询 in 的实现 方案

我们经常会有这种业务需求,根据一个条件集合去查询一张表的数据,比如: select * from all_element t where t.task_id in (List <taskids>); 在java语言中,我们需要用到JDBC来和数据库打交道,那么在JDBC中该...
  • suifeng3051
  • suifeng3051
  • 2014-04-18 17:08
  • 10053

jdbc中PreparedStatement不定参数的小技巧

jdbc中PreparedStatement对不定参数的进行设参预编译的小技巧
  • dream_broken
  • dream_broken
  • 2015-03-27 20:43
  • 7087

Spring NamedParameterJdbcTemplate 详解 解决jdbcTemplate中 in 参数的问题

NamedParameterJdbcTemplate类是基于JdbcTemplate类,并对它进行了封装从而支持命名参数特性。 NamedParameterJdbcTemplate主要提供以下三类方法:execute方法、query及queryForXXX方法、update及batchUpda...
  • z69183787
  • z69183787
  • 2014-10-20 10:42
  • 26397

关于PreparedStatement以及Jpa中in参数的设置

关于PreparedStatement以及Jpa中in参数的设置在实际开发的过程中,都会遇到sql语句需要传in的参数的问题,小白我在开发的过程中也踩了好多坑,今天这里结合一些大大给的答案,简单的总结一下使用PreparedStatement以及在JPA中使用Query时, in后面的参数设置的方法...
  • u014529211
  • u014529211
  • 2017-07-24 17:08
  • 1034

如何使PreparedStatement支持命名参数

/***********本人原创,欢迎转载,转载请保留本人信息*************//***********文章发表请与本人联系,作者保留所有权利*************/作者:wallimn电邮:wallimn@sohu.com博客:http://blog.csdn.net/wallimn...
  • wallimn
  • wallimn
  • 2009-01-08 14:08
  • 8095

sql语句中PreparedStatement的用法

一.PreparedStatement 概述 在数据库的操作过程中,PreparedStatement 对象是一个很不起眼但是记为重要的接口对象,它继承 于Statement,并与之在两方面有所不同: 1)PreparedStatement 实例包含已编译的 SQL 语句。这就是使语句“准备好”...
  • u012491514
  • u012491514
  • 2015-06-23 17:34
  • 3516

PreparedStatement的用法

 一.PreparedStatement 概述在数据库的操作过程中,PreparedStatement 对象是一个很不起眼但是记为重要的接口对象,它继承 于Statement,并与之在两方面有所不同:1)PreparedStatement 实例包含已编译的 SQL 语句。这就是使语句“准备...
  • kingskyleader
  • kingskyleader
  • 2009-11-11 23:20
  • 70943

PrepareStatement 中in like的用法

PrepareStatement的用法在Mysql中很重要,ye
  • xiaobaismiley
  • xiaobaismiley
  • 2014-09-22 23:30
  • 4054

PreparedStatement设值where in语句

情景 :select * from  table where id in(1,2,3); 程序实现: String sql ="select * from table where id in (?)"; try{ PreparedStatement ps = ...
  • yanm7788
  • yanm7788
  • 2011-11-28 10:43
  • 579

preparestatement详细介绍

传送给数据库的 SQL 语句通过一个包含两个步骤的过程来返回结果。首先准备它们,然后处理它们。借助 Statement 对象,这两个阶段对应用程序而言变成一个阶段。PreparedStatement 允许将这两个步骤分开。准备步骤在创建对象时发生,而处理步骤在对 PreparedStatement ...
  • rushkid02
  • rushkid02
  • 2012-04-21 21:54
  • 6158
    个人资料
    • 访问:9853次
    • 积分:195
    • 等级:
    • 排名:千里之外
    • 原创:8篇
    • 转载:5篇
    • 译文:0篇
    • 评论:1条
    文章分类
    最新评论