我有一个使用 JDBI 查询 Redshift 集群的程序,我正在努力使用该bindBean
功能生成适当的 SQL 语句。
@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("user@email.com", "email@user.com"))
.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()
);
}
上面的代码抛出了异常:org.jdbi.v3.core.statement.UnableToCreateStatementException: No argument factory registered for type [java.util.List<java.lang.String>]
.
我读到这可以通过注册数组类型来解决,如下所示:
public void jdbiQuery() {
.
.
Jdbi jdbi = createJdbi(JDBC_URI, USERNAME, PASSWORD);
jdbi.registerArrayType(String.class, "varchar");
.
.
}
实际上,这消除了异常,但生成的最终 SQL 语句不正确(注意 IN 子句的格式不正确)。
SELECT id FROM Users WHERE id = '1234' AND email_address IN ('{"user@email.com","email@user.com"}')
由于使用该bindList
功能的列表标识符包含在 中<>
,因此我尝试将 SQL 模板更改为:
.
.
String sqlTemplate =
"SELECT id FROM Users WHERE id = :id AND email_address IN (<emailAddresses>)";
.
这导致了以下异常:
Caused by: org.jdbi.v3.core.statement.UnableToCreateStatementException: Undefined attribute for token '<emailAddresses>'
有谁知道如何解决这个问题?欢迎任何建议:)
谢谢!