Java JPA getSingleResult() 或 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2002993/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:21:02  来源:igfitidea点击:

JPA getSingleResult() or null

javajpa

提问by Eugene Ramirez

I have an insertOrUpdatemethod which inserts an Entitywhen it doesn't exist or update it if it does. To enable this, I have to findByIdAndForeignKey, if it returned nullinsert if not then update. The problem is how do I check if it exists? So I tried getSingleResult. But it throws an exception if the

我有一个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;
}

but getSingleResultthrows an Exception.

getSingleResult抛出一个Exception.

Thanks

谢谢

采纳答案by cletus

Throwing an exception is how getSingleResult()indicates it can't be found. Personally I can't stand this kind of API. It forces spurious exception handling for no real benefit. You just have to wrap the code in a try-catch block.

抛出异常是如何getSingleResult()表明它无法找到。我个人无法忍受这种 API。它强制进行虚假异常处理而没有真正的好处。您只需要将代码包装在 try-catch 块中。

Alternatively you can query for a list and see if its empty. That doesn't throw an exception. Actually since you're not doing a primary key lookup technically there could be multiple results (even if one, both or the combination of your foreign keys or constraints makes this impossible in practice) so this is probably the more appropriate solution.

或者,您可以查询列表并查看其是否为空。那不会抛出异常。实际上,由于您在技术上没有进行主键查找,因此可能会有多个结果(即使一个、两个或外键或约束的组合在实践中都无法实现),因此这可能是更合适的解决方案。

回答by Carl Smotricz

So don't do that!

所以不要那样做!

You have two options:

您有两个选择:

  1. Run a selection to obtain the COUNT of your result set, and only pull in the data if this count is non-zero; or

  2. Use the other kind of query (that gets a result set) and check if it has 0 or more results. It should have 1, so pull that out of your result collection and you're done.

  1. 运行选择以获取结果集的 COUNT,并且仅在此计数非零时才拉入数据;或者

  2. 使用另一种查询(获取结果集)并检查它是否有 0 个或多个结果。它应该有 1,所以把它从你的结果集合中拉出来,你就完成了。

I'd go with the second suggestion, in agreement with Cletus. It gives better performance than (potentially) 2 queries. Also less work.

我同意第二个建议,同意 Cletus。它提供比(可能)2 个查询更好的性能。工作也少。

回答by Eugene Katz

I encapsulated the logic in the following helper method.

我将逻辑封装在以下辅助方法中。

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();
    }
}

回答by tpdi

Here's the same logic as others suggested (get the resultList, return its only element or null), using Google Guava and a TypedQuery.

这里的逻辑与其他人建议的逻辑相同(获取 resultList,返回其唯一元素或 null),使用 Google Guava 和 TypedQuery。

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

Note that Guava will return the unintuitive IllegalArgumentException if the result set has more than one result. (The exception makes sense to clients of getOnlyElement(), as it takes the result list as its argument, but is less understandable to clients of getSingleResultOrNull().)

请注意,如果结果集有多个结果,Guava 将返回不直观的 IllegalArgumentException。(该异常对 getOnlyElement() 的客户端有意义,因为它将结果列表作为其参数,但对 getSingleResultOrNull() 的客户端来说不太容易理解。)

回答by Rodrigo IronMan

Here's a good option for doing this:

这是一个很好的选择:

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);
}

回答by aces.

There is an alternative which I would recommend:

有一个我会推荐的替代方案:

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

This safeguards against Null Pointer Exception, guarantees only 1 result is returned.

这可以防止空指针异常,保证只返回 1 个结果。

回答by Pete Montgomery

Here's another extension, this time in Scala.

这是另一个扩展,这次是在 Scala 中。

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

With this pimp:

有了这个皮条客:

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)
}

回答by Sorter

If you wish to use the try/catch mechanism to handle this problem.. then it can be used to act like if/else. I used the try/catch to add a new record when I didn't find an existing one.

如果您希望使用 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); 
}

回答by Emmanuel Touzery

Here's a typed/generics version, based on Rodrigo IronMan's implementation:

这是一个类型化/泛型版本,基于 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);
}

回答by heenenee

Spring has a utility methodfor this:

Spring 有一个实用方法

TypedQuery<Profile> query = em.createNamedQuery(namedQuery, Profile.class);
...
return org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());