Что лучше: getSingleResult или getResultList JPA
Мне нужно получить одну строку из таблицы, и мне было интересно, какой подход лучше.
С одной стороны getSingleResult
предназначен для получения единственного результата, но он вызывает исключение. Имеет ли этот метод преимущества, связанные с getResultList
с
query.setFirstResult(0);
query.setMaxResults(1);
Ответы
Ответ 1
getSingleResult
throws NonUniqueResultException
, если имеется несколько строк. Он предназначен для получения единственного результата, когда есть действительно один результат.
То, как вы это сделали, прекрасно, и JPA спроектирован таким образом, чтобы справиться с этим. В то же время вы не можете сравнивать его с getSingleResult
любым способом, так как он не будет работать.
Однако, в зависимости от кода, над которым вы работаете, всегда лучше уточнить запрос, чтобы возвращать единый результат, если это все, что вы хотите - тогда вы можете просто вызвать getSingleResult
.
Ответ 2
Согласно эффективной Java от Джошуа Блоха:
Использовать проверенные исключения для условий, из которых может разумно ожидать восстановления. Использовать исключения во время выполнения, чтобы указать ошибки программирования.
Кредит источнику: Почему вы никогда не должны использовать getSingleResult() в JPA.
@Entity
@NamedQuery(name = "Country.findByName",
query = "SELECT c FROM Country c WHERE c.name = :name"
public class Country {
@PersistenceContext
transient EntityManager entityManager;
public static Country findByName(String name) {
List<Country> results = entityManager
.createNamedQuery("Country.findByName", Country.class)
.setParameter("name", name).getResultList();
return results.isEmpty() ? null : results.get(0);
}
}
Ответ 3
Есть альтернатива, которую я бы рекомендовал:
Query query = em.createQuery("your query");
List<Element> elementList = query.getResultList();
return CollectionUtils.isEmpty(elementList ) ? null : elementList.get(0);
Эта защита от Null Pointer Exception гарантирует, что возвращается только 1 результат.
Ответ 4
getSingleResult выбрасывает NonUniqueResultException, если существует несколько строк или нет любые строки. Он предназначен для получения единственного результата, когда есть действительно один результат.
Ответ 5
В сочетании с fetch()
использование setMaxResults(1)
может привести к частично инициализированным объектам. Например,
CriteriaQuery<Individual> query = cb.createQuery(Individual.class);
Root<Individual> root = query.from(Individual.class);
root.fetch(Individual_.contacts);
query.where(cb.equal(root.get(Individual_.id), id));
Individual i = em.createQuery(query)
.setMaxResults(1) // assertion fails if individual has 2 contacts
.getResultList()
.get(0);
assertEquals(2, i.getContacts().size());
Итак, я использую getResultList()
без ограничений - немного неудовлетворительно.