Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA getSingleResult() or null

Tags:

java

jpa

People also ask

What is query getSingleResult ()?

getSingleResult. java.lang.Object getSingleResult() Execute a SELECT query that returns a single untyped result.

Can getResultList return null?

getResultList() returns an empty list instead of null .

What is typed query?

TypedQuery. TypedQuery gives you an option to mention the type of entity when you create a query and therefore any operation thereafter does not need an explicit cast to the intended type. Whereas the normal Query API does not return the exact type of Object you expect and you need to cast.

What is NoResultException?

Class NoResultExceptiongetSingleResult() is executed on a query and there is no result to return. This exception will not cause the current transaction, if one is active, to be marked for rollback.


Throwing an exception is how getSingleResult() indicates it can't be found. Personally I can't stand this kind of API. It forces spurious exception handling for no real benefit. You just have to wrap the code in a try-catch block.

Alternatively you can query for a list and see if its empty. That doesn't throw an exception. Actually since you're not doing a primary key lookup technically there could be multiple results (even if one, both or the combination of your foreign keys or constraints makes this impossible in practice) so this is probably the more appropriate solution.


I encapsulated the logic in the following helper method.

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

Try this in Java 8:

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

Here's a good option for doing this:

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

Spring has a utility method for this:

TypedQuery<Profile> query = em.createNamedQuery(namedQuery, Profile.class);
...
return org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());

I've done (in Java 8):

query.getResultList().stream().findFirst().orElse(null);

From JPA 2.2, instead of .getResultList() and checking if list is empty or creating a stream you can return stream and take first element.

.getResultStream()
.findFirst()
.orElse(null);