Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot + JPA + Exception Handling

I'm working on a proof of concept to convert our project to a Spring Boot application. I have a repository class with 2 methods: save and find.

@Repository
public class UserDataRepo {
    private EntityManager em;

    public boolean save(UserDataModel model) {
        try {
            UserDataModel existingModel = find(model.getTable(), model.getFieldName();
            model.setId(existingModel.getId());
            this.em.merge(model);
            this.em.flush();
            return false;
        } catch (NoResultException e) {
            this.em.persist(model);
            this.em.flush();
            return true;
        }
    }

    public UserDataModel find(String table, String field) {
        Query query = this.em.createQuery(FIND_USERDATA_STATEMENT);
        query.setParameter("table", table);
        query.setParameter("fieldName", field);
        return (UserDataModel) query.getSingleResult(); // throws NoResultException
    } 
}

In my Spring Boot Application class, I have added @EnableJpaRepositories, @EnableTransactionManagement. My application starts up fine without any errors. But as you can see the save method depends on the find method to determine whether to merge or persist. If there is no record, find method throws NoResultException. What I'm observing is it never falls inside the save method's catch block. Spring Boot just throws an error saying NoResultException.

In the case of merge, it works like a charm. So it means the entity manager works fine.

I do not know what else needs to be configured. Any thoughts?

Adding error from the logs:

org.springframework.dao.EmptyResultDataAccessException: No entity found for query; nested exception is javax.persistence.NoResultException: No entity found for query
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:389)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
like image 484
Gnana Avatar asked Jun 23 '26 19:06

Gnana


2 Answers

I would not recommend this behaviour. Use of getSingleResult() like this is not recommended. Read more information on why never to use getSingleResult in JPA here. Instead try a query like this.

    Query query = this.em.createQuery(FIND_USERDATA_STATEMENT);
    query.setParameter("table", table);
    query.setParameter("fieldName", field);

    List results = query.getResultList();
    if (results.isEmpty()) {
        return null;
    }
    else if (results.size() == 1)  {
        return results.get(0);
    }
    throw new NonUniqueResultException();
like image 160
DominicEU Avatar answered Jun 25 '26 12:06

DominicEU


For simple persistence cases like this, I'd very strongly suggest looking at Spring Data JPA which would allow you to avoid having to do any of this complicated manual persistence management. If this does not work for you, i'd strongly suggest you not use Exceptions for Logic. That is, instead of relying on an exception from a failed Find query to determine if the object needs to be persisted or merged, I'd first query using a count to determine if the object exists, then, depending on that result continue with the merge or persist. In general using Exceptions in business logic is considered an anti pattern, please see: When is it OK to use exception handling for business logic?

like image 28
Ben M Avatar answered Jun 25 '26 12:06

Ben M