我打算用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