Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.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
使用Java8可选返回的JPA最佳实践?_Java_Jpa_Java 8 - Fatal编程技术网

使用Java8可选返回的JPA最佳实践?

使用Java8可选返回的JPA最佳实践?,java,jpa,java-8,Java,Jpa,Java 8,我喜欢Java8的语义。我在DAO中使用了很多这样的代码: public Optional<User> findBy(String username) { try { return Optional.of( emp.get().createQuery("select u from User u where u.username = :username" , User.class) .setParameter("username"

我喜欢Java8的语义。我在DAO中使用了很多这样的代码:

  public Optional<User> findBy(String username) {
    try {
      return Optional.of(
        emp.get().createQuery("select u from User u where u.username = :username" , User.class)
        .setParameter("username" , username)
        .setMaxResults(1)
        .getSingleResult()
      );
    } catch (NoResultException e) {
      return Optional.empty();
    }
  }
它工作得很好,但这样的代码try-catch-NoResultException分散在我的DAO上。我必须捕捉异常,它会以某种方式降低性能

我想知道这是不是最好的解决办法?或者有更好的解决方案,而不必尝试捕获

如果由于JPA中定义了NoResultException而无法实现,那么是否有“模板化”此类工作流的快捷方式


谢谢。

当然,如果您可以使用lambdas的魔力将其模板化

从@FunctionInterface开始定义lambda的合同:

@FunctionalInterface
public interface DaoRetriever<T> {
    T retrieve() throws NoResultException;
}
所以在这里,->emp.得到。。。是捕获检索行为的lambda。允许接口DAORRetriever抛出NoResultException,因此lambda也是

或者,我将使用TypedQuery的另一种方法——getResultList——并将代码更改如下:

public Optional<User> findBy(String username) {
    return emp.get().createQuery("select u from User u where u.username = :username", User.class)
            .setParameter("username", username)
            .setMaxResults(1)
            .getResultList()
            .stream()
            .findFirst();
}

这样做的优点是更简单,但缺点是如果有其他结果,就直接丢弃它们。

Boris走上了正确的道路,但可以做得更好。我们需要更多的抽象。此转换与DAO无关

我们需要一个不同算术的族或函数接口,将抛出异常的lambda转换为不抛出异常的lambda。FunctionalJava做到了这一点:

所以我们有一系列Try类:Try0、Try1等等

public interface Try0<A, Z extends Exception> {
    A f() throws Z;
}
我们希望将其转换为不引发异常的函数:

static public <A, E extends Exception> Supplier<Validation<E, B>> toSupplierValidation(final Try0<A, E> t) {
    return () -> {
        try {
            return Validation.success(t.f());
        } catch (Exception e) {
            return Validation.fail((E) e);
        }
    };
}
请注意,验证在失败的情况下是一个异常,如果成功,则是常规值。如果您不关心异常,那么可以将失败案例转换为空可选案例,将成功案例转换为可选案例中的值。此方法看起来像Boris的方法,但没有与之无关的dao引用:

static public <A, E extends Exception> Supplier<Optional<A>> toSupplierOptional(final Try0<A, E> t) {
    return () -> {
        try {
            return Optional.of(t.f());
        } catch (Exception e) {
            return Optional.empty();
        }
    };
}

最好的解决方案是修复引发异常的代码,我猜是getSingleResult。没有结果不是异常情况,因此引发异常是不合适的。@T.J.Crowder这是JPA规范的一部分,由JPA提供商实现-不确定这是一个选项。@BoristheSpider:Yikes。看在上帝的份上,这是怎么通过审查的@T.J.克劳德设计委员会。。。结局总是不好。Hibernate的等价项只返回null,没有结果。但是,对于具有多个实际结果的情况,卡片中仍然存在一个例外。JPA查询不返回null的原因是,查询可能选择某个列,并且该列的内容为null。这与没有这样的争吵是不同的。这里有一些讨论:哇,太棒了,无论是模板还是stream.findFirst解决方案。我学到了很多。谢谢。@smallufo我的荣幸。只是稍微更改了SMI—使其成为一个泛型类。setMaxResults1保证不会获取额外的结果—我将使用该习惯用法创建一个模板accept query,调用setMaxResults1.getResultList.stream.findFirst。顺便说一句,我不会调用findOrEmpty方法——只要给定可选的返回类型,find就足够了。}catch NoResultException ex{这不是一个好主意,除非它是一个例外情况,它将被重新引用而不是被记录。谢谢。你的解决方案太抽象了,我无法理解。也许我需要一些时间来消化。谢谢你的FunctionalJava解决方案。我以前没有接触过FJ。如果DaoRetriever接口代表任何需要的函数,它会更好确定无参数,返回结果或引发一般异常。这是Try0接口。如果我将Try1编辑为Try0以匹配前面的示例,可能会有所帮助。
static public <A, E extends Exception> Supplier<Validation<E, B>> toSupplierValidation(final Try0<A, E> t) {
    return () -> {
        try {
            return Validation.success(t.f());
        } catch (Exception e) {
            return Validation.fail((E) e);
        }
    };
}
static public <A, E extends Exception> Supplier<Optional<A>> toSupplierOptional(final Try0<A, E> t) {
    return () -> {
        try {
            return Optional.of(t.f());
        } catch (Exception e) {
            return Optional.empty();
        }
    };
}