JPA best practices and Java 8 optional return?

I like the semantics of Java 8. I use a lot of such code in my 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();
    }
  }

It works well, but such code (trying to catch noresultexception) is scattered on my Dao I have to catch exceptions, which will reduce performance

I wonder if it is the best solution? Or any better solution, no try catch?

If this is not possible (because no resultexception is defined in JPA), is there any shortcut to "templating" this workflow?

thank you.

Solution

If you can imitate it, use the magic of the lamb!

Starting from @ functionalinterface, define the contract of lambda:

@FunctionalInterface
public interface DaoRetriever<T> {
    T retrieve() throws NoResultException;
}

This is a single method interface (or SMI) that encapsulates the behavior of your method

Now create a practical way to use SMI:

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

Now, use import static in your calling code. Your method is:

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

So here, () – > EMP Get()... Is a lambda that captures the retrieval behavior Interface daoretriever is allowed to throw noresultexception, so is lambda

Alternatively, I'll use another method of typedquery - getresultlist - and change the code as follows:

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

This has the advantage of being simpler, but if so, the disadvantage of simply discarding other results

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>