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

sma*_*ufo 15 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" , username)
        .setMaxResults(1)
        .getSingleResult()
      );
    } catch (NoResultException e) {
      return Optional.empty();
    }
  }
Run Code Online (Sandbox Code Playgroud)

它运行良好,但这样的代码(尝试捕获NoResultException)散布在我的DAO上.我必须捕捉异常,这会以某种方式降低性能.

我想知道它是否是最好的解决方案?或任何更好的解决方案,没有try-catch?

如果不可能(因为在JPA中定义了NoResultException),任何"模板化"这样的工作流程的快捷方式?

谢谢.

Bor*_*der 26

如果当然你可以使用lambdas的魔力来模板化它!

首先用a @FunctionalInterface定义lambda的契约:

@FunctionalInterface
public interface DaoRetriever<T> {
    T retrieve() throws NoResultException;
}
Run Code Online (Sandbox Code Playgroud)

这是一个单一方法接口(或SMI),它将封装您方法的行为.

现在创建一个实用程序方法来使用SMI:

public static <T> Optional<T> findOrEmpty(final DaoRetriever<T> retriever) {
    try {
        return Optional.of(retriever.retrieve());
    } catch (NoResultException ex) {
        //log
    }
    return Optional.empty();
}
Run Code Online (Sandbox Code Playgroud)

现在,使用import static您的调用代码,您的上述方法变为:

public Optional<User> findBy(String username) {
    return findOrEmpty(() ->
            emp.get().createQuery("select u from User u where u.username = :username", User.class)
                    .setParameter("username", username)
                    .setMaxResults(1)
                    .getSingleResult());
}
Run Code Online (Sandbox Code Playgroud)

所以这里() -> emp.get()...是一个捕获检索行为的lambda.在interface DaoRetriever被允许抛出NoResultException这样的拉姆达过.

或者,我会使用另一种方法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();
}
Run Code Online (Sandbox Code Playgroud)

这具有更简单的优点,但是如果有的话,简单地丢弃其他结果的缺点.