【发布时间】:2016-02-01 20:35:34
【问题描述】:
我正在进行概念验证,以将我们的项目转换为 Spring Boot 应用程序。我有一个带有 2 种方法的存储库类:保存和查找。
@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
}
}
在我的 Spring Boot Application 类中,我添加了@EnableJpaRepositories、@EnableTransactionManagement。我的应用程序启动正常,没有任何错误。但是正如你所看到的,save 方法依赖于 find 方法来确定是合并还是持久化。如果没有记录,find 方法抛出 NoResultException。我观察到的是它永远不会落入 save 方法的 catch 块中。 Spring Boot 只是抛出一个错误,说 NoResultException。
在合并的情况下,它就像一个魅力。所以这意味着实体管理器工作正常。
我不知道还需要配置什么。有什么想法吗?
从日志中添加错误:
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)
【问题讨论】:
-
看起来您要捕获的异常是
org.springframework.dao.EmptyResultDataAccessException而不是NoResultException。NoResultException嵌套在外部异常中,因此您的try { } catch块不会看到它 -
@MrWiggles 我将其更改为捕获 EmptyResultDataAccessException,但它仍然不属于 catch 块。使用 Spring Boot 时应该以不同方式映射异常还是使用 Spring Boot 配置持久性的方式?
-
您可以暂时将您的 catch 块更改为
Throwable以查看实际引发的异常是什么。 -
@MrWiggles 我试过了,实际的异常是一样的:javax.persistence.NoResultException: No entity found for query。给出一个上下文,现有的 Web 应用程序是 spring+jersey+hibernate,它在 tomcat 中部署为战争。逻辑工作正常。异常在 save 内的 catch 块中被捕获。我正在研究这个 POC,以展示是否可以将其捆绑为阴影 jar 并将其配置为 Spring Boot 应用程序。除了异常不会传播到父块的逻辑之外,每个微服务似乎都可以工作。
-
@MrWiggles 我刚刚在 find 方法中添加了“throws NoResultException”,当我使用 Spring Boot 启动应用程序时它就起作用了。不过很奇怪。
标签: java spring hibernate jpa spring-boot