Я использую JDBI с Dropwizard, и у меня проблема с быстрыми запросами. У меня есть апи конечную точку, которая выглядит следующим образом:JDBI Fluent Query Issue
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 запросов для запуска. Если бы я добавил еще один параметр lookup (например, accountId), это означало, что теперь мне нужно иметь 6 запросов (по 1 для каждой возможности) и 6 операторов if для определения того, какой запрос запускать.
Есть ли простой способ обойти это с помощью JDBI? Я рассмотрел возможность @Define, однако это представляет риск SQL-инъекции. Email и Nickname - это строки.
Я бы в идеале нужен только один запрос:
@SqlQuery(" SELECT * FROM ACCOUNT WHERE NICKNAME = :nickname AND EMAIL = :email " )
public Account getAccount(@Bind("nickname") String nickname, @Bind("email") String email);
Если ник был нулевым это игнорировать бы требование ника и просто запросить от электронной почты. Что-то вроде этого возможно?
EDIT/UPDATE:
Я теперь сделал это для того, чтобы очистить мой код немного:
@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 дао использовать @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());
Я бы предпочел не использовать определение, хотя хотел бы сохранить логику запросов в DAO. Было бы хорошо, если бы что-то подобное было вообще возможно:
SELECT * FROM ACCOUNT WHERE @IfNotNull(id = :id)
AND @IfNotNull(email = :email) AND @IfNotNull(nickname = :nickname)
Хорошая идея, но технически вы должны использовать (коалесценции (: электронная почта, '') = '' или по электронной почте =: электронная почта), чтобы соответствовать bcam909, если (Strings.isNullOrEmpty (электронная почта)!). То же самое с псевдонимом. – alecswan
Это будет работать, если оба адреса электронной почты и псевдоним не равны нулю. Если оба псевдонима и адрес электронной почты были пустыми, он будет возвращать все учетные записи. Я должен был бы добавить проверку перед вызовом этого запроса, чтобы удостовериться, что псевдоним и электронная почта были не пустыми или пустыми. – bcam909