I have an application that accesses the database by using JDBC PreparedStatements. To keep the data access generic, the method that accesses the database uses the PreparedStatement setObject method heavily (see question discussing a similar approach). Some pseudocode to illustrate:
public ResultSet getResultSet(String sql, List<Object> parameters) throws SQLException {
PreparedStatement preparedStatement = db.getConnection().prepareStatement(sql);
for(int i = 0; i < parameters.size(); i++) {
preparedStatement.setObject(i+1, parameters.get(i));
}
return preparedStatement.executeQuery();
}
This reduces code duplication, as getResultSet(String, List) can be used to perform different queries. However, it also risks SQLExceptions being thrown at runtime. Example situation:
- Someone invokes getResultSet("SELECT columnWithVarchar2Type FROM someTable WHERE columnWithVarchar2Type = ?", Arrays.asList(someCustomObject));
- db.getConnection().prepareStatement(sql) returns an OraclePreparedStatement
- preparedStatement.setObject throws a java.sql.SQLException 'Invalid column type'
The behavior of OraclePreparedStatement is probably justified; it doesn't know how to map someCustomObject to columnWithVarchar2Type. However, to the caller of getResultSet(String, List) this is a surprise - after all, the caller provided a list with an object, just as was requested!
The question is: Given the differences between the implementations of PreparedStatement, is there a way to introduce any compile-time safety to the signature of the getResultSet method to prevent callers from passing parameters that will throw SQLExceptions at runtime?
Complete compile-time safety is of course impossible, but is there a way to use e.g. generics to prevent someone passing in parameters that will always result in an SQLException independently of the SQL that is passed?
Edit: This is in all likelihood even theoretically impossible (nothing prevents someone from implementing PreparedStatement and deciding to never throw SQLExceptions or to always throw SQLExceptions from setObject()). However, it would be nice to know how ORMs go around this problem.