我喜欢
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(); } }
它工作得很好,但是这样的代码(尝试捕获NoResultException)分散在我的DAO上.我必须抓住异常,这会降低性能.
我想知道它是否是最佳解决方案?或任何更好的解决方案,没有try-catch?
如果不可能(因为JPA中定义了NoResultException),任何“模板化”这种工作流的快捷方式?
谢谢.
解决方法
如果你可以模仿它,使用羊羔的魔法!
从@FunctionalInterface开始,定义lambda的合同:
@FunctionalInterface public interface DaoRetriever<T> { T retrieve() throws NoResultException; }
现在创建一个使用SMI的实用方法:
public static <T> Optional<T> findOrEmpty(final DaoRetriever<T> retriever) { try { return Optional.of(retriever.retrieve()); } catch (NoResultException ex) { //log } return Optional.empty(); }
现在,在你的调用代码中使用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()); }
所以在这里,() – > emp.get()…是一个捕获检索行为的lambda.接口DaoRetriever被允许抛出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(); }
这具有更简单的优点,但是如果有的话,简单地丢弃其他结果的缺点.