JPA getSingleResult () или нуль - PullRequest
114 голосов
/ 05 января 2010

У меня есть метод insertOrUpdate, который добавляет Entity, когда он не существует, или обновляет его, если он существует. Чтобы включить это, я должен findByIdAndForeignKey, если он вернул null вставить, если нет, то обновить. Проблема в том, как проверить, существует ли он? Поэтому я попытался getSingleResult. Но это исключение, если

public Profile findByUserNameAndPropertyName(String userName, String propertyName) {
    String namedQuery = Profile.class.getSimpleName() + ".findByUserNameAndPropertyName";
    Query query = entityManager.createNamedQuery(namedQuery);
    query.setParameter("name", userName);
    query.setParameter("propName", propertyName);
    Object result = query.getSingleResult();
    if (result == null) return null;
    return (Profile) result;
}

но getSingleResult бросает Exception.

Спасибо

Ответы [ 19 ]

3 голосов
/ 18 мая 2017

Недокументированный метод uniqueResultOptional в org.hibernate.query.Query должен помочь. Вместо того, чтобы поймать NoResultException, вы можете просто позвонить query.uniqueResultOptional().orElse(null).

2 голосов
/ 22 января 2018

Я решил это, используя List<?> myList = query.getResultList(); и проверив, равно ли myList.size() нулю.

2 голосов
/ 08 апреля 2016

Объединяя полезные биты существующих ответов (ограничивая количество результатов, проверяя, что результат уникален) и используя установленное имя метода (Hibernate), мы получаем:

/**
 * Return a single instance that matches the query, or null if the query returns no results.
 *
 * @param query query (required)
 * @param <T> result record type
 * @return record or null
 */
public static <T> T uniqueResult(@NotNull TypedQuery<T> query) {
    List<T> results = query.setMaxResults(2).getResultList();
    if (results.size() > 1) throw new NonUniqueResultException();
    return results.isEmpty() ? null : results.get(0);
}
1 голос
/ 17 марта 2011

Здесь используется та же логика, что и другие (получить resultList, вернуть единственный элемент или значение NULL), используя Google Guava и TypedQuery.

public static <T> getSingleResultOrNull(final TypedQuery<T> query) {
    return Iterables.getOnlyElement(query.getResultList(), null); 
}

Обратите внимание, что Guava вернет неинтуитивную исключительную ситуацию IllegalArgumentException, если результирующий набор имеет более одного результата. (Исключение имеет смысл для клиентов getOnlyElement (), так как он принимает список результатов в качестве аргумента, но менее понятно для клиентов getSingleResultOrNull ().)

1 голос
/ 07 августа 2012

Вот еще одно расширение, на этот раз в Scala.

customerQuery.getSingleOrNone match {
  case Some(c) => // ...
  case None    => // ...
}

С этим сутенером:

import javax.persistence.{NonUniqueResultException, TypedQuery}
import scala.collection.JavaConversions._

object Implicits {

  class RichTypedQuery[T](q: TypedQuery[T]) {

    def getSingleOrNone : Option[T] = {

      val results = q.setMaxResults(2).getResultList

      if (results.isEmpty)
        None
      else if (results.size == 1)
        Some(results.head)
      else
        throw new NonUniqueResultException()
    }
  }

  implicit def query2RichQuery[T](q: TypedQuery[T]) = new RichTypedQuery[T](q)
}
0 голосов
/ 13 мая 2019

Я добился этого, получив список результатов и проверив, пуст ли он

public boolean exist(String value) {
        List<Object> options = getEntityManager().createNamedQuery("AppUsers.findByEmail").setParameter('email', value).getResultList();
        return !options.isEmpty();
    }

Это так раздражает, что getSingleResult() выбрасывает исключения

Броски:

  1. NoResultException - если нет результата
  2. NonUniqueResultException - если более одного результата и некоторые другие исключения, о которых вы можете получить больше информации из их документации
0 голосов
/ 16 февраля 2019

Посмотрите этот код:

return query.getResultList().stream().findFirst().orElse(null);

Когда вызывается findFirst(), может быть выдано исключение NullPointerException.

лучший подход:

return query.getResultList().stream().filter(Objects::nonNull).findFirst().orElse(null);

0 голосов
/ 10 января 2019

Это работает для меня:

Optional<Object> opt = Optional.ofNullable(nativeQuery.getSingleResult());
return opt.isPresent() ? opt.get() : null;
0 голосов
/ 04 ноября 2015

Таким образом, все решения «попробуйте переписать без исключения» на этой странице имеют небольшую проблему. Либо его не вызывает исключение NonUnique, но также и в некоторых неправильных случаях (см. Ниже).

Я думаю, что правильное решение (возможно) это:

public static <L> L getSingleResultOrNull(TypedQuery<L> query) {
    List<L> results = query.getResultList();
    L foundEntity = null;
    if(!results.isEmpty()) {
        foundEntity = results.get(0);
    }
    if(results.size() > 1) {
        for(L result : results) {
            if(result != foundEntity) {
                throw new NonUniqueResultException();
            }
        }
    }
    return foundEntity;
}

Возвращает значение null, если в списке есть элемент 0, возвращает неуникальное, если в списке есть разные элементы, но не возвращает неуникальное, если один из выбранных вами элементов выбран неправильно и возвращает один и тот же объект более одного раза.

Не стесняйтесь комментировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...