Сравнение строк JPA

#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).