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 ]

238 голосов
/ 05 января 2010

Создание исключения - это то, как getSingleResult() указывает, что оно не может быть найдено. Лично я терпеть не могу такого рода API. Это заставляет ложную обработку исключений без реальной выгоды. Вам просто нужно обернуть код в блок try-catch.

Кроме того, вы можете запросить список и посмотреть, если он пуст. Это не исключение. На самом деле, поскольку технически вы не выполняете поиск первичного ключа, результатов может быть несколько (даже если один, оба или комбинация ваших внешних ключей или ограничений делают это невозможным на практике), так что это, вероятно, более подходящее решение.

31 голосов
/ 21 мая 2010

Я инкапсулировал логику в следующем вспомогательном методе.

public class JpaResultHelper {
    public static Object getSingleResultOrNull(Query query){
        List results = query.getResultList();
        if (results.isEmpty()) return null;
        else if (results.size() == 1) return results.get(0);
        throw new NonUniqueResultException();
    }
}
22 голосов
/ 17 июня 2011

Вот хороший вариант для этого:

public static <T> T getSingleResult(TypedQuery<T> query) {
    query.setMaxResults(1);
    List<T> list = query.getResultList();
    if (list == null || list.isEmpty()) {
        return null;
    }

    return list.get(0);
}
17 голосов
/ 31 декабря 2016

Попробуйте это в Java 8:

Optional first = query.getResultList().stream().findFirst();
14 голосов
/ 23 июля 2014

Spring имеет служебный метод для этого:

TypedQuery<Profile> query = em.createNamedQuery(namedQuery, Profile.class);
...
return org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());
7 голосов
/ 12 января 2013

Если вы хотите использовать механизм try / catch для решения этой проблемы ... тогда он может быть использован как if / else Я использовал try / catch, чтобы добавить новую запись, когда я не нашел существующую.

try {  //if part

    record = query.getSingleResult();   
    //use the record from the fetched result.
}
catch(NoResultException e){ //else part
    //create a new record.
    record = new Record();
    //.........
    entityManager.persist(record); 
}
6 голосов
/ 21 сентября 2017

Я сделал (в Java 8):

query.getResultList().stream().findFirst().orElse(null);
6 голосов
/ 27 марта 2013

Вот типизированная / обобщенная версия, основанная на реализации Rodrigo IronMan:

 public static <T> T getSingleResultOrNull(TypedQuery<T> query) {
    query.setMaxResults(1);
    List<T> list = query.getResultList();
    if (list.isEmpty()) {
        return null;
    }
    return list.get(0);
}
5 голосов
/ 05 января 2010

Так что не делайте этого!

У вас есть два варианта:

  1. Запустите выбор, чтобы получить СЧЕТ вашего результирующего набора, и вытащите толькоданные, если это число ненулевое;или

  2. Используйте другой тип запроса (который получает набор результатов) и проверьте, имеет ли он 0 или более результатов.У него должно быть 1, так что извлеките это из вашей коллекции результатов, и все готово.

Я согласился бы со вторым предложением, в согласии с Cletus.Это дает лучшую производительность, чем (потенциально) 2 запроса.Также меньше работы.

4 голосов
/ 02 июля 2012

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

Query query = em.createQuery("your query");
List<Element> elementList = query.getResultList();
return CollectionUtils.isEmpty(elementList ) ? null : elementList.get(0);

Это гарантирует исключение Null Pointer, гарантирует, что возвращается только 1 результат.

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