PreparedStatement is usually preferred over Statement for these reasons :
- in general, it's more secure. When a Statement is constructed dynamically from user input, it's vulnerable to SQL injection attacks. PreparedStatement is less vulnerable in this way (see below).
- there is usually no need to worry about escaping special characters.
- if repeated compilation is avoided, its performance is usually better.
In general, it seems safest to use a Statement only when the SQL is of fixed, known form, with no parameters.
If PreparedStatement is used correctly, then it does indeed provide complete protection against SQL Injection attacks. However, if it's used incorrectly, then it's still wide open to such attacks.
The SQL statement passed to PreparedStatment is simply an unvalidated String, in the sense that there's no checking for '?' values. If the String has been constructed using '?' placeholders for all data, then it has indeed been constructed correctly.
But PreparedStatement has no built-in mechanism to prevent the inexperienced or inattentive programmer from passing a String which, by mistake, does not always use a '?' placeholder where it should.
Such Strings are wide open to SQL Injection attacks.