2014年12月16日 星期二

[Java] java.sql.PreparedStatement 值得注意的地方

某日,我想用java.sql.PreparedStatement做一個可以用程式去指定where的條件 ,

原本我認為應該會合成這樣的一個SQL:

"SELECT id, name, color FROM animal where 1=1 and name='cat';"

But, 卻出現了錯誤。
嚴重: null
org.postgresql.util.PSQLException: 

ERROR: syntax error at or near "$1"

程式碼如下:
public static void main(String[] args) {

     Connection conn;
    String url = "jdbc:postgresql://localhost/demo?"
            + "user=postgres&password=abcd1234";
    String sql = "SELECT id, name, color FROM animal where 1=1 ?;";
    try {
        //載入驅動器
        Class.forName("org.postgresql.Driver");
        //取得Connection(取得成功表示己與資料庫連上線)
        conn = DriverManager.getConnection(url);

        PreparedStatement st=conn.prepareStatement(sql);
        st.setString(1, "and name='cat'");

        //查詢資料(把查到的資料放進ResultSet)
        ResultSet rs = st.executeQuery();
        //讀取ResultSet中的資料
        while (rs.next()) {
            //id 是數值列態
            System.out.print(rs.getInt("id") + "\t");
            //name 及 color 是String型態
            System.out.print(rs.getString("name") + "\t");
            System.out.print(rs.getString("color") + "\n");
        }
    } catch (ClassNotFoundException e) {
        System.exit(1);
    } catch (SQLException ex) {
        Logger.getLogger(DemoPreparedStatement.class.getName()).
                log(Level.SEVERE, null, ex);
    }
}
用Debug Mode看了一下合成出來的SQL:
SELECT id, name, color FROM animal where 1=1 'and name=''cat'''
沒錯,它自動幫我再單引號的地方,再多加了一個單引號,並且在字串的前後也加上單引號,

因為在SQL語法中,2個單引號表示你要輸入的是一個單引號字元。這是它貼心的地方,

可以避免發生SQL Injection 。雖然這樣也會造成某使用上的些限制,

但PreparedStatement 對於只需替換參數的SQL語法有較好的效能。

以上是小弟在實作時遇到問題的經驗分享。

沒有留言:

張貼留言