我打算用对象替换重复执行的 Statement 对象PreparedStatement
以提高性能。我正在使用 MySQL 函数now()
和字符串变量等参数。
PreparedStatement
我见过的大多数查询都包含常量值(如10
和字符串"New York"
)作为?
查询中使用的参数。我将如何使用now()
, 和变量等函数作为参数?是否有必要?
在查询中使用 s 而不是实际值?我很困惑。
我打算用对象替换重复执行的 Statement 对象PreparedStatement
以提高性能。我正在使用 MySQL 函数now()
和字符串变量等参数。
PreparedStatement
我见过的大多数查询都包含常量值(如10
和字符串"New York"
)作为?
查询中使用的参数。我将如何使用now()
, 和变量等函数作为参数?是否有必要?
在查询中使用 s 而不是实际值?我很困惑。
如果您有一个来自用户输入的变量,那么您必须使用 ? 而不是连接字符串。用户可能会恶意输入字符串,如果您将字符串直接放入 SQL 中,它可能会运行您不想要的命令。
我意识到这个被过度使用了,但它完美地说明了这一点:
如果您有变量,请使用“?”
int temp = 75;
PreparedStatement pstmt = con.prepareStatement(
"UPDATE test SET num = ?, due = now() ");
pstmt.setInt(1, temp);
pstmt.executeUpdate():
生成如下所示的 sql 语句:
UPDATE test SET num = 75, due = now();
您不必在 PreparedStatement 中使用占位符。就像是:
PreparedStatement stmt = con.prepareStatement("select sysdate from dual");
会工作得很好。但是,您不能使用占位符然后将函数调用绑定到它。像这样的东西不能用来调用 sysdate 函数:
PreparedStatement stmt = con.prepareStatement("select ? from dual");
stmt.setSomethingOrOther(1, "sysdate");
如果您正在调用 SQL 服务器的内置函数,请使用PreparedStatement。
如果您正在调用已加载到 SQL 服务器上的存储过程,请使用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";