首页 > 代码库 > JDBC的PreparedStatement语句使用记录

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进行批处理》

JDBC的PreparedStatement语句使用记录