我打算用PreparedStatement
對象替換重複執行的Statement對象以提高性能。我使用的參數如MySQL函數now()
和字符串變量。Java的PreparedStatement如何工作?
大多數PreparedStatement
查詢我所看到的包含常數值(如10
和字符串像"New York"
)作爲用於查詢的?
參數。我將如何去使用像now()
這樣的函數和變量作爲參數?是否有必要在查詢中使用?
而不是實際值?我很困惑。
我打算用PreparedStatement
對象替換重複執行的Statement對象以提高性能。我使用的參數如MySQL函數now()
和字符串變量。Java的PreparedStatement如何工作?
大多數PreparedStatement
查詢我所看到的包含常數值(如10
和字符串像"New York"
)作爲用於查詢的?
參數。我將如何去使用像now()
這樣的函數和變量作爲參數?是否有必要在查詢中使用?
而不是實際值?我很困惑。
如果你有變量,使用'?'
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();
如果您有來自用戶的輸入變量,這是必要的,你使用?而不是連接字符串。用戶可能會惡意輸入一個字符串,並且如果將字符串直接放入SQL中,它可以運行您不想要的命令。
我知道這個人是濫用,但它完美地說它:
我相信,你的意思是SQL注入。 – 2009-01-07 04:20:41
你不必在一個PreparedStatement使用佔位符。例如:
PreparedStatement stmt = con.prepareStatement("select sysdate from dual");
會工作得很好。但是,您不能使用佔位符,然後將函數調用綁定到它。像這樣的事情不能被用來調用SYSDATE功能:
PreparedStatement stmt = con.prepareStatement("select ? from dual");
stmt.setSomethingOrOther(1, "sysdate");
如果您呼叫建立在您的SQL服務器的功能,然後使用PreparedStatement。
如果您正在調用已加載到SQL Server的存儲過程,請使用CallableStatement。
使用問號作爲您傳遞的函數/過程參數和函數返回值的佔位符。
我已經開發了一個功能,可以讓你在你的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";
你是問,如果你能使用字符串值函數代替字符串文字?你問你是否可以使用int值函數代替文字整數?你能提供一個代碼片段嗎? – 2009-01-07 02:54:33