We upgraded spring from v4 to 6.0.22 and Hibernate from v4 to 6.4.9 and we spotted that jakarta.persistence.NoResultException
is not wrapped into EmptyResultDataAccessException
. This seems to be a bug.
Comment From: quaff
It's a feature not bug.
Comment From: jhoeller
Where specifically is it not getting wrapped? We generally do wrap NoResultException
in EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible
. Are you possibly invoking an EntityManager
directly in which case you will get the raw JPA exceptions by design? You may register a PersistenceExceptionTranslationPostProcessor
then but this will only affect the proxy callers of your service/repository beans, not the immediate ´EntityManager` operations either.
Comment From: trueMiskin
Yes, we invoke EntityManager
methods. Normal service looks like this:
@Service
public class ServiceName implements IServiceName {
@PersistenceContext
EntityManager em;
@Transactional(readOnly = true)
@Override
public List<ISomeObject> findSomething(IParamObject param) {
Query q = em.createNamedQuery("QueryName");
q.setParameter("param", param);
return q.getResultList();
}
}
In spring 4, exceptions were wrapped even when calling EntityManager
methods. Has anything changed since then? I have not seen any note on that in the migration guides.
By registering the PersistenceExceptionTranslationPostProcessor
will exceptions be wrapped by spring? Is registering done by adding these lines to the config?
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
Comment From: jhoeller
Generally, such a PersistenceExceptionTranslationPostProcessor
is necessary indeed, automatically applying exception translation to all @Repository
beans. You could also apply it to your @Service
classes through declaring the repositoryAnnotationType
property on PersistenceExceptionTranslationPostProcessor
accordingly, setting it to org.springframework.stereotype.Service
.
Not sure why this happened automatically for you with Spring 4. JdbcTemplate
and co perform it automatically within the delegate itself but we never really had such automatic translation for a plain JPA EntityManager
...
Comment From: trueMiskin
I added this:
<bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">
<property name="repositoryAnnotationType" value="org.springframework.stereotype.Service" />
</bean>
to config file but errors show up:
Bean with name 'serviceName' has been injected into other beans [serviceName2] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.
I don't get why this change raises this error. Maybe a good solution is to use raw JPA exceptions.
Comment From: jhoeller
It looks like there is a circular reference between two of your services: In such a case, proxying might happen too late which is what that exception message says. Breaking a circular reference through a lazy reference is usually straightforward, so that e.g. "serviceName2" would use an @Lazy Service serviceName
declaration or ObjectFactory<Service> serviceName
if you'd like to avoid annotations.
Comment From: jhoeller
Since the framework bits seem to work as intended here, I'm closing this issue.