JDBC的PreparedStatement語句使用記錄

<<JDBC爲何要使用PreparedStatement而不是Statement>> 列舉了爲何PreparedStatement要優於Statement,其中最主要的兩點是更快的性能和防止SQL注入攻擊。在文章的末尾提到了一個侷限性:PreparedStatement不容許一個佔位符(?)有多個值,並提出瞭如何在**IN**子句使用PreparedStatement的棘手問題。html

《JDBC PreparedStatement IN clause alternative approaches》 給出了四種方案:java

1. Execute Single Queriessql

2. Using Stored Procedureapp

3. Creating PreparedStatement Query dynamically性能

4. Using NULL in PreparedStatement Queryui

第三和第四方案看起來更合適些,第四種方案能夠看做是第三種方案的擴展。spa

第三種使用下面代碼構建SQL語句code

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。htm

因此就有了第四種方案:blog

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進行批處理》

相關文章
相關標籤/搜索