Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA getSingleResult()或null_Java_Jpa - Fatal编程技术网

Java JPA getSingleResult()或null

Java JPA getSingleResult()或null,java,jpa,Java,Jpa,我有一个insertOrUpdate方法,当实体不存在时插入一个实体,如果存在则更新它。要启用此功能,我必须findbyiandforeignkey,如果它返回null则插入,如果没有,则更新。问题是如何检查它是否存在?所以我尝试了getSingleResult。但是如果 public Profile findByUserNameAndPropertyName(String userName, String propertyName) { String namedQuery = Prof

我有一个
insertOrUpdate
方法,当实体不存在时插入一个
实体
,如果存在则更新它。要启用此功能,我必须
findbyiandforeignkey
,如果它返回
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
抛出一个
异常


谢谢

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

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

所以不要这样做

您有两个选择:

  • 运行选择以获取结果集的计数,并且仅当该计数非零时才拉入数据;或

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


  • 我同意第二个建议,同意克莱特斯的意见。它提供了比(可能)2个查询更好的性能。也减少了工作量。

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

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

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

    public static <T> getSingleResultOrNull(final TypedQuery<T> query) {
        return Iterables.getOnlyElement(query.getResultList(), null); 
    }
    
    公共静态getSingleResultOrNull(最终类型查询){
    返回Iterables.getOnlyElement(query.getResultList(),null);
    }
    

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

    这里有一个很好的选项:

    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);
    }
    
    publicstatict getSingleResult(TypedQuery查询){
    query.setMaxResults(1);
    List=query.getResultList();
    if(list==null | | list.isEmpty()){
    返回null;
    }
    返回列表。获取(0);
    }
    
    我推荐一种替代方案:

    Query query = em.createQuery("your query");
    List<Element> elementList = query.getResultList();
    return CollectionUtils.isEmpty(elementList ) ? null : elementList.get(0);
    
    Query Query=em.createQuery(“您的查询”);
    List elementList=query.getResultList();
    返回CollectionUtils.isEmpty(元素列表)?null:elementList.get(0);
    

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

    这里是另一个扩展,这次是在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)
    }
    

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

    以下是基于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);
    }
    
    public static T getSingleResultOrNull(TypedQuery查询){
    query.setMaxResults(1);
    List=query.getResultList();
    if(list.isEmpty()){
    返回null;
    }
    返回列表。获取(0);
    }
    
    Spring为此提供了:

    TypedQuery<Profile> query = em.createNamedQuery(namedQuery, Profile.class);
    ...
    return org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());
    
    TypedQuery query=em.createNamedQuery(namedQuery,Profile.class);
    ...
    返回org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());
    
    因此,本页中所有的“尝试无例外地重写”解决方案都有一个小问题。要么它不会抛出非唯一异常,要么在某些错误情况下也不会抛出它(见下文)

    我认为正确的解决办法是(也许)这样:

    public static L getSingleResultOrNull(TypedQuery){
    List results=query.getResultList();
    L foundEntity=null;
    如果(!results.isEmpty()){
    foundEntity=results.get(0);
    }
    如果(results.size()>1){
    对于(L结果:结果){
    如果(结果!=foundEntity){
    抛出新的ununiqueresultexception();
    }
    }
    }
    返回实体;
    }
    
    如果列表中有0个元素,则返回null;如果列表中有不同的元素,则返回ununique;但如果选择的一个元素设计不正确,则不返回ununique,并多次返回同一对象


    请随意评论。

    结合现有答案的有用部分(限制结果数量,检查结果是否唯一)并使用已建立的方法名称(Hibernate),我们得到:

    /**
    *返回与查询匹配的单个实例,如果查询未返回任何结果,则返回null。
    *
    *@param查询(必需)
    *@param结果记录类型
    *@返回记录或空
    */
    公共静态T uniqueResult(@NotNull TypedQuery查询){
    List results=query.setMaxResults(2.getResultList();
    如果(results.size()>1)抛出新的ununiquereSultException();
    返回results.isEmpty()?null:results.get(0);
    }
    
    在Java 8中尝试以下操作:

    Optional first = query.getResultList().stream().findFirst();
    
    query.getResultList().stream().findFirst().orElse(null);
    

    org.hibernate.query.query中未记录的方法
    uniquerysultoptional
    ,应该可以做到这一点。您不必捕获
    NoResultException
    ,只需调用
    query.uniqueResultOptional().orElse(null)
    即可(在Java 8中):


    我通过使用
    List myList=query.getResultList()解决了这个问题
    并检查myList.size()是否等于零。

    这对我来说很有用:

    Optional<Object> opt = Optional.ofNullable(nativeQuery.getSingleResult());
    return opt.isPresent() ? opt.get() : null;
    
    Optional opt=Optional.ofNullable(nativeQuery.getSingleResult());
    返回opt.isPresent()?opt.get():null;
    
    查看以下代码:

    返回query.getResultList().stream().findFirst().orElse(null)

    调用
    findFirst()
    时,可能会抛出NullPointerException

    我最喜欢的一条裙子
    query.getResultList().stream().findFirst().orElse(null);
    
    Optional<Object> opt = Optional.ofNullable(nativeQuery.getSingleResult());
    return opt.isPresent() ? opt.get() : null;
    
    public boolean exist(String value) {
            List<Object> options = getEntityManager().createNamedQuery("AppUsers.findByEmail").setParameter('email', value).getResultList();
            return !options.isEmpty();
        }
    
    .getResultStream()
    .findFirst()
    .orElse(null);