2009-01-07 55 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";