I have a program using JDBI to query a Redshift cluster, and I'm struggling to generate the appropriate SQL statement using the bindBean
functionality.
@Data @Builder
public static class User {
private String id;
private List<String> emailAddresses;
}
private Jdbi createJdbi(
@NonNull String jdbcUri,
@NonNull String username,
@NonNull String password) {
RedshiftSimpleDataSource redshiftDataSource = new RedshiftSimpleDataSource();
redshiftDataSource.setUrl(jdbcUri);
redshiftDataSource.setUser(username);
redshiftDataSource.setPassword(password);
return Jdbi.create(redshiftDataSource);
}
public void jdbiQuery() {
User user = User.builder()
.id("1234")
.emailAddresses(List.of("[email protected]", "[email protected]"))
.build();
String sqlTemplate =
"SELECT id FROM Users WHERE id = :id AND email_address IN (:emailAddresses)";
Jdbi jdbi = createJdbi(JDBC_URI, USERNAME, PASSWORD);
List<String> userIds = jdbi.withHandle(
handle -> handle.createQuery(sqlTemplate)
.bindBean(user)
.mapTo(String.class)
.list()
);
}
The code above threw the exception: org.jdbi.v3.core.statement.UnableToCreateStatementException: No argument factory registered for type [java.util.List<java.lang.String>]
.
I read that this could be fixed by registering the array type as follows:
public void jdbiQuery() {
.
.
Jdbi jdbi = createJdbi(JDBC_URI, USERNAME, PASSWORD);
jdbi.registerArrayType(String.class, "varchar");
.
.
}
Indeed, that removed the exception, but then the final SQL statement generated was incorrect (notice how the IN clause is not correctly formatted).
SELECT id FROM Users WHERE id = '1234' AND email_address IN ('{"[email protected]","[email protected]"}')
Since the list identifiers to use the bindList
functionality are enclosed in <>
, I tried changing the SQL template to:
.
.
String sqlTemplate =
"SELECT id FROM Users WHERE id = :id AND email_address IN (<emailAddresses>)";
.
which resulted in the following exception:
Caused by: org.jdbi.v3.core.statement.UnableToCreateStatementException: Undefined attribute for token '<emailAddresses>'
Does anyone know how to solve this issue? Any suggestion is welcome :)
Thanks!