Java + JPA: поиск пользователя в базе данных По имени и фамилии выведите слишком много результатов. Есть ли способ лучше?

0

В настоящее время моя реализация подобна этой, поэтому, если тип пользователя Peter Smith, тогда я бы разделил строку запроса следующим образом:

String[] name = searchQuery.split(" "); //searchQuery is type String

тогда я бы прошел через name array, и для каждого name я сопоставляю его с полями имени и фамилии в моем db, как показано ниже

@NamedQuery(name="User.findUserByName",
    query="select c from User c where c.fname LIKE :param OR c.lname LIKE :param"),

public List<User> findUser(String searchParam){
    Query query = em.createNamedQuery("User.findUserByName");
    query.setParameter("param", "%" + searchParam + "%");
    return query.getResultList();
}

однако, если я это сделаю, он вернет слишком много результатов (все, что связано с Питером, будет отображаться, и все, что связано с Смитом, также будет). Есть ли лучший способ сделать это?

Я использую EclipseLink btw

Теги:
database
jpa
jpa-2.0

1 ответ

3

Если бы я был вами, я бы использовал API критериев. Вот пример реализации:

public List<User> findUsersByName(final String firstName,
    final String lastName){

    final boolean hasFirst = firstName != null && firstName.length() > 0;
    // if you use Apache Commons / Lang, do it like this:
    // final boolean hasFirst = StringUtils.isNotBlank(firstName);

    final boolean hasLast = lastName != null && lastName.length() > 0;
    if(!hasFirst && !hasLast){
        // or throw IllegalArgumentException
        return Collections.emptyList();
    }
    final CriteriaBuilder cb = em.getCriteriaBuilder();
    final CriteriaQuery<User> query = cb.createQuery(User.class);
    final Root<User> root = query.from(User.class);
    if(hasFirst && hasLast){
        query.where(cb.and(
            likeExpression(cb, root,"lname", lastName),
            likeExpression(cb, root, "fname", firstName)
            ));
    } else if(hasFirst){
        query.where(likeExpression(cb, root,"fname", firstName));
    } else{
        query.where(likeExpression(cb, root,"lname", lastName));
    }
    return em.createQuery(query).getResultList();
}

private static Predicate likeExpression(final CriteriaBuilder cb,
    final Root<User> root,
    final String path, String parameter){
    return cb.like(root.<String> get(path), "*"+parameter.trim()+"*");
}

Теперь вы можете легко создавать перегруженные версии этого метода:

public List<User> findUsersByFullName(final String fullName){
    final String[] parts = fullName.split("\\s+");
    if(parts.length != 2){
        // probably you should assemble first name from all parts
        // except the last, but I'm lazy
        throw new IllegalArgumentException("Bad name: " + fullName);
    }
    return findUsersByName(parts[0], parts[1]);
}

public List<User> findUsersByLastName(final String lastName){
    return findUsersByName(null, lastName);
}

public List<User> findUsersByFirstName(final String firstName){
    return findUsersByName(firstName, null);
}

Ссылка:

  • 0
    Круто, я попробую. Возможно, у вас будет пара вопросов. Спасибо. +1
  • 0
    Есть ли причина, по которой вы используете final для всех ваших переменных?
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню