82

Before I posted this question, I already looked this, but I couldn't get what I was looking for.

I know that for the query I wrote there may exist only one row or none at all. So, there is not reason for me to use getResultList().

Here is my code:

String hql="from DrawUnusedBalance where unusedBalanceDate= :today";
Query query=em.createQuery(hql);
query.setParameter("today",new LocalDate());

DrawUnusedBalance drawUnusedBalance= 
    (DrawUnusedBalance)query.getSingleResult();// we can have only a
                                               // single datum per day
//`System.out.println(drawUnusedBalance.toString());`

The problem is, if there is no row, it throws an exception, and if not it works fine. I know the problem but I am also looking for the best solution.

What I wanted is, if there is no row in the DB I wanted to get a null object (instead of getting an exception) so I will insert a new data, if it is not null, I just want to update it.

There is one way to handle this, which I believe is not the right way to do it. It is: I will have a try-catch block and if it throws an exception I can write to insert new data in to the DB on the catch block. But I believe there will be a better way.

1
  • Try uniqueResultOptional(), which returns (you guessed it) an Optional<T>. Commented Nov 13, 2023 at 16:22

6 Answers 6

126

Yes. You need to use the try/catch block, but no need to catch the Exception. As per the API it will throw NoResultException if there is no result, and its up to you how you want to handle it.

DrawUnusedBalance drawUnusedBalance = null;
try{
drawUnusedBalance = (DrawUnusedBalance)query.getSingleResult()
catch (NoResultException nre){
//Ignore this because as per your logic this is ok!
}

if(drawUnusedBalance == null){
 //Do your logic..
}
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks ManuPK ...But I still have to write some code which is creating an object and persist do a DB ..in the Catch block .... and I thought that will not be a good way to persist data from a catch block ... Though tnx for your response.
I feel there is nothing wrong in catching a checked exception and taking an alternative path. That why the JPA is giving you option on how you want to handle it. Actually the method you are looking for is available in hibernate which is not available with JPA.
@user1017111 I got your problem in writing code inside the catch. I have updated the answer slightly to make the code readable.
Interestingly this solutions is discussed here: stackoverflow.com/questions/2002993/jpa-getsingleresult-or-null
@ManuPK : javax.persistence.NoResultException is not checked Exception. Its unChecked Exception.
|
45

When using java 8, you may take advantage of stream API and simplify code to

return (YourEntityClass) entityManager.createQuery()
....
.getResultList()
.stream().findFirst();

That will give you java.util.Optional

If you prefer null instead, all you need is

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

2 Comments

The question is related to getSingleResult(), not to .getResultList(). It's even stated in the description.
He's still taking a single element from getResultList() though.
7

You mentioned getting the result list from the Query, since you don't know that there is a UniqueResult (hence the exception) you could use list and check the size?

if (query.list().size() == 1) 

Since you're not doing a get() to get your unique object a query will be executed whether you call uniqueResult or list.

6 Comments

For now, I am using the query.list().isEmpty() to see if there is any data returned ... I thought it would be easy for the programmer if we were getting a null object like the get() method. Thanks
No problem. IsEmpty was obviously what I meant when I wrote my answer ;)
@Alex: The only problem with this approach is that you need to use an additional query to get the count. It might be a performance overhead.
Why would you need an additional query to get the count? You've already got a list containing all of the entities matching the query.
@Alex : Ok. Then query.list() should be stored separably and checked. I got your point and you are right.I got confused by the if condition.
|
4

When you don't know whether there are any results, use getResultList().

List<User> foundUsers = (List<User>) query.getResultList();
        if (foundUsers == null || foundUsers.isEmpty()) {
            return false;
        }
User foundUser = foundUsers.get(0);

3 Comments

OK, it's a suggestion rather than an answer. But might be useful to others.
When you don't know whether there are any results, use getResultList(). List<User> foundUsers = (List<User>) query.getResultList(); if (foundUsers == null || foundUsers.isEmpty()) { return false; } User foundUser = foundUsers.get(0);
This looks worse no?
4

Another option is to use uniqueResultOptional() method, which gives you Optional in result:

String hql="from DrawUnusedBalance where unusedBalanceDate= :today";
Query query=em.createQuery(hql);
query.setParameter("today",new LocalDate());

Optional<DrawUnusedBalance> drawUnusedBalance=query.uniqueResultOptional();

Comments

0
String hql="from DrawUnusedBalance where unusedBalanceDate= :today";
DrawUnusedBalance drawUnusedBalance = em.unwrap(Session.class)
    .createQuery(hql, DrawUnusedBalance.class)
    .setParameter("today",new LocalDate())
    .uniqueResultOptional()
    .orElseThrow(NotFoundException::new);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.