#string #jpa #comparison #equals #jpql
#строка #jpa #сравнение #равно #jpql
Вопрос:
Я написал простую систему входа в систему, используя JPQL-запрос, который всегда не возвращает результата:
public boolean check(String name, String password) {
final String qstring="SELECT e FROM Muser e WHERE e.name = '" name "'";
Muser user;
try{
user = em.createQuery(qstring, Muser.class).getSingleResult();
}
catch(NoResultException e){
return false;
}
return password.equals(user.getPassword());
}
Когда я изменил его на собственный запрос:
user = (Muser) em.createNativeQuery(qstring, Muser.class).getSingleResult();
или выражение int:
final String qstring="SELECT e FROM Muser e WHERE e.id = " id;
Все идет хорошо. В чем проблема? Миллион благодарностей!
Комментарии:
1. Не храните пароли в виде открытого текста: хэшируйте их. Создайте запрос, аргументы которого в нем: используйте параметры (чтобы избежать внедрения кода).
Ответ №1:
Возможно, проблема со сравнением строк в вашем поставщике JPA. Вы тестируете это на данных, чувствительных к регистру?
Вы также могли бы попробовать (и это предпочтительный способ) использовать параметры вместо того, чтобы создавать свой оператор вручную. Это не только безопаснее (предотвращает внедрение SQL), но и быстрее: не только для Java (вы не объединяете строки), но и для DB (запрос может быть подготовлен один раз для всех выполнений). Это может быть что-то вроде этого:
final String qstring = "SELECT e FROM Muser e WHERE e.name = :name";
TypedQuery<Muser> query = em.createQuery(qstring, Muser.class);
query.setParameter("name", name);
user = query.getSingleResult();
Комментарии:
1. Я перепробовал все возможности: использование параметров, изменение различных реализаций (EclipseLink и Hibernate), в то время как строка ТОЧНО такая же, как в DB, но она все еще не работает…
2. @user1036998 как определяется ваша сущность? Как поле ‘name’ аннотируется (или определяется в orm.xml )? Какой столбец определен в базе данных?
3. @Id @Столбец (имя = «NAME», длина = 12) общедоступная строка getName() { возвращает this.name ; } public void setName(имя строки) { this.name = name; } Спасибо вам за вашу помощь!
4. @ArchBuddhiCat используете ли вы JPA для генерации своей схемы БД или работаете над готовой? Не могли бы вы опубликовать, как определяется столбец базы данных? Какое значение вы передаете в качестве параметра ‘name’?
5. Сначала я создал таблицу с именем MUSER в базе данных Oracle, а затем определил объект. Столбец name определяется как тип CHAR длиной 12. Позже я попробую удалить таблицу и позволить JPA создавать таблицу автоматически. Параметр name передается из компонента EJB, который вызывается страницей JSF.
Ответ №2:
Я думаю, проблема в сравнении строк.Мое решение этой проблемы таково:
использовать нижний регистр для сравнения.
final String qstring = "SELECT e FROM Muser e WHERE LOWER(e.name) = :name";
TypedQuery<Muser> query = em.createQuery(qstring, Muser.class);
query.setParameter("name", name.toLowerCase());
user = query.getSingleResult();
Комментарии:
1. Я бы использовал «ГДЕ НИЖЕ (e.name ) = LOWER(:name)» и избегайте выполнения name.toLowerCase() в Java. Храните все в одном месте, то есть разделяйте проблемы (SoC).