JDBI Fluent查询问题

时间:2015-02-06 02:09:47

标签: sql dropwizard jdbi

我正在使用带有Dropwizard的JDBI,并且遇到了流畅查询的问题。我有一个api端点,如下所示:

public Response getAccount(@QueryParam("nickname") String nickname, @QueryParam("email") String email);

我试图避免编写以下3个查询:

@SqlQuery(  " SELECT * FROM ACCOUNT WHERE EMAIL = :email "  )

public Account getAccountByEmail(@Bind("email") String email);


@SqlQuery( " SELECT * FROM ACCOUNT WHERE NICKNAME = :nickname " )

public Account getAccountByNickname(@Bind("nickname") String nickname);


@SqlQuery( " SELECT * FROM ACCOUNT WHERE NICKNAME = :nickname AND EMAIL = :email "  )

public Account getAccount(@Bind("nickname") String nickname, @Bind("email") String email);

这也意味着我的方法getAccount的实现有3个,如果检查...昵称,没有电子邮件,电子邮件,没有昵称,电子邮件和昵称,以确定要运行的3个查询中的哪一个。如果我要添加另一个查找参数(例如accountId),这意味着我现在需要有6个查询(每种可能性为1)和6个if语句来确定要运行的查询。

有没有一种简单的方法可以通过JDBI解决这个问题?我研究了@Define的可能性但是这会带来SQL注入的风险。电子邮件和昵称都是字符串。

理想情况下,我只需要一个查询:

@SqlQuery( " SELECT * FROM ACCOUNT WHERE NICKNAME = :nickname AND EMAIL = :email "  )

public Account getAccount(@Bind("nickname") String nickname, @Bind("email") String email);

如果昵称为null,则会忽略昵称要求,只查询电子邮件。这样的事情可能吗?

修改/更新:

我现在已经这样做了,以便稍微清理我的代码:

    @SqlQuery(" SELECT * FROM ACCOUNT WHERE <query> ")
    public Account getAccount(@Bind("id") Long id, @Bind("nickname") String nickname, @Bind("email") String email, @Define("query") String query);

我已经更新了我的JDBI dao以使用@Define。通过这样做,我可以减少我的6个查询(每个案例1个查询,因为有3个查询字段),6个if语句可以减少到1个查询,3个if语句。

    Account account = null;
    StringBuilder query = new StringBuilder();

    if(accountId != null) {
        query.append(" ID = :id ");
    }
    if(!Strings.isNullOrEmpty(nickname)) {
        if(query.length() > 0) query.append(" AND ");
        query.append(" NICKNAME = :nickname ");
    }
    else if(!Strings.isNullOrEmpty(email)) {
        if(query.length() > 0) query.append(" AND ");
        query.append(" EMAIL = :email ");
    }

    account = accountDAO.getAccount(accountId, nickname, email, query.toString());

我宁愿不必使用define,因为我想在DAO中保留我的查询逻辑。如果像这样的事情很可能会很好:

SELECT * FROM ACCOUNT WHERE @IfNotNull(id = :id) 
AND @IfNotNull(email = :email) AND @IfNotNull(nickname = :nickname)

1 个答案:

答案 0 :(得分:1)

我们也可以在单个查询中实现这一点,而不是在java代码中构造sql。虽然有点hacky。

select * from account where
( COALESCE(:email, NULL) IS NULL OR email = :email) and
( COALESCE(:nickname, NULL) IS NULL OR nickname = :nickname) ;