I'm attempting to use JDBC to call a SQL query in Oracle that uses bind variables with the :varName syntax. The query was written for interactive use and looks like this:
select * from foo where bar = :mybar;
If I could, I would just change the query to use JDBC standard "?" symbols to represent the variable, and use setString(1, "x") to set them. Unfortunately, I cannot change the text of the query as it has been validated for use in medical applications.
I attempted to wrap it in additional code that sets the value for :mybar in approximately the same fashion as an interactive user, following examples from Oracle, but I'm getting the JDBC error:
java.sql.SQLException: Missing IN or OUT parameter at index:: 1.
The wrapped version produces a string that looks like this
variable mybar VARCHAR
begin
:mybar := 'x'
select * from foo where bar = :mybar;
end
The Oracle Driver is a V12 driver loaded via:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1.0</version>
</dependency>
This is my java code:
try(Connection conn = getConnection()) {
PreparedStatement stmt = stmt(conn, study, start, end);
ResultSet resultSet = stmt.executeQuery();
return Table.read().db(resultSet);
}
...
private PreparedStatement stmt(Connection connection, String study, LocalDate start, LocalDate end) throws SQLException {
String query = wrapValidatedQuery(study, start, end);
return connection.prepareStatement(query);
}
The wrapValidatedQuery() method returns the query as shown above.
This (below) is a standalone version that should be executable with changes to the db params.
public static void main(String[] args) throws Exception {
String username = "name";
String password = "pwd";
Connection conn = null;
Statement stmt;
int port = 1521;
String hostname = "host";
String dbName = "db_name";
String jdbcUrl = "jdbc:oracle:thin:@" + hostname + ":" + port + "/" + dbName;
try {
String driver = "oracle.jdbc.driver.OracleDriver";
Class.forName(driver).newInstance();
conn = DriverManager.getConnection(jdbcUrl, username, password);
stmt = conn.createStatement();
String query =
" VARIABLE mybar VARCHAR;\n" +
" begin;\n" +
" :mybar := 'x'; \n" +
" select * from foo where bar = :mybar;\n" +
" end;";
ResultSet rs = stmt.executeQuery(query);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
throw new RuntimeException("Didn't get results.");
}
Is there a solution that will work without changing the query?