Question

I always read the blog Java Revisited and today I was reading the article Why use PreparedStatement in Java JDBC - Example Tutorial. At one point the author writes about parameterization of queries, that is better, safer and more performative use the parameterization provided by the API than to concatenate strings and uses the examples below:

SQL Query 1: PreparedStatement with String concatenation

String loanType = getLoanType();
PreparedStatement pstmt = conn.prepareStatement("select banks from loan where loan_type=" + loanType);

SQL Query 2: Parameterized query using PreparedStatement

PreparedStatement pstmt = conn.prepareStatement("select banks from loan where loan_type=?");
pstmt.setString(1, loanType);

The author explains that by using the parameterization, JDBC driver will check the data and with concatenated String the driver doesn't, it will just run the sent SQL, i.e., if we have that famous OR 1 = 1 the query will always return true and there's the classic SQL Injection case.

What was not clear to me is why one is more performative than the other, plus, in case I have a value that is always the same, is this true too?

PreparedStatement pstmt = conn.prepareStatement(select * from users where active = 'S');

Or is it more performative use as below:

PreparedStatement pstmt = conn.prepareStatement(select * from users where active = ?);
pstmt.setString(1, "S");

Another question, in this case I think the security issue is the same, because as there is no parameter passing through the user there is no attack, right?

Was it helpful?

Solution

If the parameter truly never changes, then using a literal is acceptable. However, depending on the database platform, passing in a parameter value as a literal that will change may cause less than optimal performance.

When you prepare a statement, the database will parse the SQL and create an execution plan of the best way to locate the results (using its optimizer). This may involve several steps, including a 'hard' parse and a 'soft' parse.

When you prepare a statement with parameterized values, the database will parse the SQL and cache the parsed execution plan. You can then execute the prepared statement multiple times, and only change the parameter's value being sent to the DB. The db can re-use the cached execution plan w/o having to 'hard' parse the SQL again.

When you execute the SQL statement repeatedly with an embedded literal parameter, the database had to perform a hard parse on each execution, hence; potentially more processing time.

OTHER TIPS

The security is the same. The added security benefit of using Prepared Statements is that it validates user input to protect against SQL injection. Where there is no user input, there is no security risk.

If you want to make a similar database call multiple times with different data, it is much more efficient to use a single Prepared Statement using parameters rather than building a new Prepared Statement for each instance using string concatenation. If it's just a one-time call then I can't imagine performance would be affected much either way.

The performance gain is there in the case that you use the same statement multiple times with different parameter values, as the preparation - which includes a compiling and optimizing step of the SQL statement by the database engine - is only executed one time - at least with some JDBC drivers/DB engines. And if you have a fix value that does not come from the user, there is no need to use prepared statements. Neither from the performance standpoint, nor are there injection issues.

The primary advantage (and in my opinion, the single definitive advantage) of using the PreparedStatement over the normal Statement is to parameterize queries - so that you can accept queries dynamically at run time (and this is a huge advantage when you need some direction from the end user on how to proceed). Also, a PreparedStatement is designed to optimize execution time in the way it runs the query. Simple Statements will directly execute the query being passed. So since you are using PreparedStatement, I would suggest that you go with option 2 (from your question) as passing parameters dynamically using 'markers' (? symbol) is the advantage of using a PreparedStatement.

Now comes the question of how do you proceed if the parameter value never changes - that is simply a matter of opinion. In that case, my suggestion would be to go with a straight string as a query and to not use parameters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top