zoukankan      html  css  js  c++  java
  • JDBC的PreparedStatement语句使用记录

    <<JDBC为什么要使用PreparedStatement而不是Statement>> 列举了为什么PreparedStatement要优于Statement,其中最主要的两点是更快的性能和防止SQL注入攻击。在文章的末尾提到了一个局限性:PreparedStatement不允许一个占位符(?)有多个值,并提出了如何在**IN**子句使用PreparedStatement的棘手问题。

    《JDBC PreparedStatement IN clause alternative approaches》 给出了四种方案:

    1. Execute Single Queries

    2. Using Stored Procedure

    3. Creating PreparedStatement Query dynamically

    4. Using NULL in PreparedStatement Query

    第三和第四方案看起来更合适些,第四种方案可以看作是第三种方案的扩展。

    第三种使用下面代码构建SQL语句

    private static String createQuery(int length) {
            String query = "select empid, name from Employee where empid in (";
            StringBuilder queryBuilder = new StringBuilder(query);
            for( int i = 0; i< length; i++){
                queryBuilder.append(" ?");
                if(i != length -1) queryBuilder.append(",");
            }
            queryBuilder.append(")");
            return queryBuilder.toString();
        }

    这种方式虽然可行,但是如果输入的参数个数发生变化,就不会get the PreparedStatement benefit of caching and reusing the execution plan。

    所以就有了第四种方案:

    public class JDBCPreparedStatementNULL {
     
        private static final String QUERY = "select empid, name from Employee where empid in ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        private static final int PARAM_SIZE = 10;
        public static void printData(int[] ids){
             
            if(ids.length > PARAM_SIZE){
                System.out.println("Maximum input size supported is "+PARAM_SIZE);
                //in real life, we can write logic to execute in batches, for simplicity I am returning
                return;
            }
            Connection con = DBConnection.getConnection();
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                ps = con.prepareStatement(QUERY);
                 
                int i = 1;
                for(; i <=ids.length; i++){
                    ps.setInt(i, ids[i-1]);
                }
                 
                //set null for remaining ones
                for(; i<=PARAM_SIZE;i++){
                    ps.setNull(i, java.sql.Types.INTEGER);
                }
                 
                rs = ps.executeQuery();
                     
                while(rs.next()){
                    System.out.println("Employee ID="+rs.getInt("empid")+", Name="+rs.getString("name"));
                }
                     
                //close the resultset here
                try{
                    rs.close();
                } catch(SQLException e){}
                 
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                try {
                    ps.close();
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    在第三种方案的基础上,我们确定最大参数个数,除了输入的参数外,剩余参数全部用setNull()置为空。这样又可以重用执行计划和预处理的cache。

    More:PreparedStatement and Statement可以批量执行,参考《使用JDBC进行批处理》

  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/wangyinhui/p/4123144.html
Copyright © 2011-2022 走看看