JavaのPreparedStatementはどのように機能しますか?
-
03-07-2019 - |
質問
繰り返し実行されるStatementオブジェクトを PreparedStatement
オブジェクトに置き換えて、パフォーマンスを改善する予定です。 MySQL関数 now()
などの引数と文字列変数を使用しています。
ほとんどの 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ステートメントを生成します。
UPDATE test SET num = 75, due = now();
他のヒント
ユーザー入力からの変数がある場合、?を使用することが不可欠です。文字列を連結するのではなく。ユーザーは文字列を悪意を持って入力する可能性があり、文字列をSQLに直接ドロップすると、意図しないコマンドが実行される可能性があります。
これは使い古されていることはわかっていますが、完全に言っています:
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";