2009-01-07 61 views
4

我打算用PreparedStatement對象替換重複執行的Statement對象以提高性能。我使用的參數如MySQL函數now()和字符串變量。Java的PreparedStatement如何工作?

大多數PreparedStatement查詢我所看到的包含常數值(如10和字符串像"New York")作爲用於查詢的?參數。我將如何去使用像now()這樣的函數和變量作爲參數?是否有必要在查詢中使用?而不是實際值?我很困惑。

+0

你是問,如果你能使用字符串值函數代替字符串文字?你問你是否可以使用int值函數代替文字整數?你能提供一個代碼片段嗎? – 2009-01-07 02:54:33

回答

8

如果你有變量,使用'?'

int temp = 75; 
PreparedStatement pstmt = con.prepareStatement(
    "UPDATE test SET num = ?, due = now() "); 
pstmt.setInt(1, temp); 
pstmt.executeUpdate(): 

產生SQL statment,看起來像:

UPDATE test SET num = 75, due = now(); 
10

如果您有來自用戶的輸入變量,這是必要的,你使用?而不是連接字符串。用戶可能會惡意輸入一個字符串,並且如果將字符串直接放入SQL中,它可以運行您不想要的命令。

我知道這個人是濫用,但它完美地說它:

Little Bobby Tables

+2

我相信,你的意思是SQL注入。 – 2009-01-07 04:20:41

0

你不必在一個PreparedStatement使用佔位符。例如:

PreparedStatement stmt = con.prepareStatement("select sysdate from dual"); 

會工作得很好。但是,您不能使用佔位符,然後將函數調用綁定到它。像這樣的事情不能被用來調用SYSDATE功能:

PreparedStatement stmt = con.prepareStatement("select ? from dual"); 
stmt.setSomethingOrOther(1, "sysdate"); 
0

如果您呼叫建立在您的SQL服務器的功能,然後使用PreparedStatement

如果您正在調用已加載到SQL Server的存儲過程,請使用CallableStatement

使用問號作爲您傳遞的函數/過程參數和函數返回值的佔位符。

0

我已經開發了一個功能,可以讓你在你的SQL查詢中使用命名參數:

private PreparedStatement generatePreparedStatement(String query, Map<String, Object> parameters) throws DatabaseException 
    { 
     String paramKey = ""; 
     Object paramValue = null; 
     PreparedStatement statement = null; 
     Pattern paramRegex = null; 
     Matcher paramMatcher = null; 
     int paramIndex = 1; 

     try 
     { 
      //Create the condition 
      paramRegex = Pattern.compile("(:[\\d\\w_-]+)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); 
      paramMatcher = paramRegex.matcher(query); 
      statement = this.m_Connection.prepareStatement(paramMatcher.replaceAll("?"), 
           ResultSet.TYPE_FORWARD_ONLY, 
           ResultSet.CONCUR_READ_ONLY, 
           ResultSet.HOLD_CURSORS_OVER_COMMIT); 

      //Check if there are parameters 
      paramMatcher = paramRegex.matcher(query); 
      while (paramMatcher.find()) 
      { 
       paramKey = paramMatcher.group().substring(1); 
       if(parameters != null && parameters.containsKey(paramKey)) 
       { 
        //Add the parameter 
        paramValue = parameters.get(paramKey); 
        if (paramValue instanceof Date) 
        { 
         statement.setDate(paramIndex, (java.sql.Date)paramValue);     
        } 
        else if (paramValue instanceof Double) 
        { 
         statement.setDouble(paramIndex, (Double)paramValue);     
        } 
        else if (paramValue instanceof Long) 
        { 
         statement.setLong(paramIndex, (Long)paramValue);     
        } 
        else if (paramValue instanceof Integer) 
        { 
         statement.setInt(paramIndex, (Integer)paramValue);     
        } 
        else if (paramValue instanceof Boolean) 
        { 
         statement.setBoolean(paramIndex, (Boolean)paramValue);     
        } 
        else 
        { 
         statement.setString(paramIndex, paramValue.toString());  
        } 
       } 
       else 
       { 
        throw new DatabaseException("The parameter '" + paramKey + "' doesn't exists in the filter '" + query + "'"); 
       } 

       paramIndex++; 
      } 
     } 
     catch (SQLException l_ex) 
     { 
      throw new DatabaseException(tag.lib.common.ExceptionUtils.getFullMessage(l_ex)); 
     } 

     return statement; 
    } 

你可以用這種方式:

Map<String, Object> pars = new HashMap<>(); 
pars.put("name", "O'Really"); 
String sql = "SELECT * FROM TABLE WHERE NAME = :name";