JAVA: проблема именованных строк - PullRequest
6 голосов
/ 16 августа 2010

Здравствуйте, ребята, у меня возникают проблемы с точными совпадениями при выполнении NamedQuery.

В настоящее время я использую что-то вроде этого:

@NamedQuery(name = MyClass.GET_ENTRY_BY_NAME, query = "select e from Entry e where e.name =:"+ Entry.NAME )

...

Query query = em.createNamedQuery(MyClass.GET_ENTRY_BY_NAME);
        query.setParameter(Entry.NAME, myEntry.getName());

Это работает в большинстве случаев, однако я заметилчто в случае, если пользователь передает имя файла с пробелом в конце, namedQuery игнорирует этот символ.Например:

Query query = em.createNamedQuery(MyClass.GET_ENTRY_BY_NAME);
        query.setParameter(Entry.NAME, myEntry.getName()+ " ");

Вернет тот же результат, что и предыдущий запрос.В обход моей проверки «действительной записи».Другими словами, я бы хотел, чтобы запрос вообще не возвращал ни одной записи и позже обрабатывал ошибку.

Один из обходных путей, о котором я мог бы подумать, - это поместить одинарные кавычки вокруг моего параметра в namedQuery, например так:

@NamedQuery(name = MyClass.GET_ENTRY_BY_NAME, query = "select e from entry e where e.name =':"+ Entry.NAME "'")

Тем не менее, мой код будет испорчен, если строка содержит одинарные кавычки ...

Есть идеи, ребята?

Ответы [ 2 ]

4 голосов
/ 16 августа 2010

Я провел некоторое исследование в JPA и обнаружил, что он выполняет автоматическую обрезку для CHAR, я не уверен, что это ведет себя так же со строками, но так как это происходит со мной ... Я так думаю. Единственный способ обойти это - установить какой-либо атрибут в объекте сеанса DatabaseLogin (см. http://www.eclipse.org/eclipselink/api/1.1/org/eclipse/persistence/sessions/DatabaseLogin.html#setShouldTrimStrings).

Ну, я не хотел портить свойства сеанса, поэтому я решил сделать какую-то проверку и выдать то же исключение, что и улов NoResultException в моем коде.

Я в основном взял результат из базы данных и сравнил поле со строкой, которую я использовал:

query.setParameter(Entry.NAME, myEntry.getName());

...

if(!StringUtils.equals(result.getName(), myEntry.getName()){
   do a cool throw just like NoResultException Catch
}

Мне также пришлось включить функцию обрезки axtavt! Это просто для того, чтобы убедиться, что если в базе данных есть столбец с завершающими пробелами и он соответствует параметру, заданному пользователем, он будет включен в качестве правильного ответа. Например:

Запись в базе данных: Name = "Flavio" - Обрезается с помощью Function = "Flavio".

Переданный параметр: Name = "Flavio" - обрезается автоматической функцией JPA = "Flavio".

Если он вообще не обрезается, он просто сравнивает «Flavio» с «Flavio», возвращая NoResult, когда предполагалось вернуть эту запись.

Гадкий обходной путь, но пока нет другого способа остановить автообрезку, нам придется просто использовать такие вещи.

Спасибо за все остальные ответы !!

4 голосов
/ 16 августа 2010

Полагаю, это происходит потому, что поле вашей базы данных объявлено как CHAR(...), и поэтому сохраненные значения заполняются пробелами, которые не учитываются операцией =.

Итак, вы можете объявитьполе вашей базы данных как VARCHAR(...) или используйте встроенную функцию trim:

query = "select e from Entry e where trim(trailing from e.name) =:"+ Entry.NAME
...