我正在使用org.springframework.data.jpa.repository.JpaRepository存储方法来保存实体。我认为save方法来自CrudRepository接口。我从服务类调用这个save方法。
try {
studentLog = studentsLogRepository.save(studentLog);
} catch (DataIntegrityViolationException dive) {
LOGGER.warn("Constraint violation occurred. Cannot insert the same record twice.", dive);
}
但问题是DataIntegrityViolationException
在catch区块中没有出现问题。相反,我在后面的日志中看到。
java.sql.BatchUpdateException: ORA-00001: unique constraint (QA_VPP.UX_TVPPC_TRAN_LOG_1) violated
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10296) ~[ojdbc6-11.2.0.2.0.jar:11.2.0.2.0]
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:216) ~[ojdbc6-11.2.0.2.0.jar:11.2.0.2.0]
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297) ~[commons-dbcp-1.3.jar:1.3]
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297) ~[commons-dbcp-1.3.jar:1.3]
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) ~[hibernate-core-3.6.7.Final.jar:3.6.7.Final]...
和
2016-12-28 10:13:52,655 LL="DEBUG" CR="1_1482920032_407_357_l73q069_VPP" RE="1482920032407" DE="1" TR="tomcat-http--12" LN="o.s.o.j.JpaTransactionManager" Initiating transaction rollback after commit exception
org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:321) ~[spring-orm-3.2.9.RELEASE.jar:3.2.9.RELEASE]
at org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossible(DefaultJpaDialect.java:121) ~[spring-orm-3.2.9.RELEASE.jar:3.2.9.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517) ~[spring-orm-3.2.9.RELEASE.jar:3.2.9.RELEASE]
at
我甚至尝试捕获不起作用的ConstraintViolationException。我认为spring数据将数据层异常包装到DataAccessException,在这种情况下是它的子类DataIntegrityViolationException。那为什么异常没有被抓住?我的服务方法未使用@Transactional
答案 0 :(得分:1)
exception。 因此,直到事务提交未完成为止,因此需要在范围之外进行捕获
示例TODO 服务等级
studentLog = studentsLogRepository.save(studentLog);
Catch at controller class
try {
call student service
} catch (DataIntegrityViolationException dive) {
LOGGER.warn("Constraint violation occurred. Cannot insert the same record twice.", dive);
或使用全局异常处理程序通过控制器建议执行相同操作
答案 1 :(得分:0)
正在发生的事情是,在调用方法.save()
时,Spring告诉EntityManager持久化实体,这只会使它在持久性上下文中得到管理和持久化。实体中的更改可能不会立即与数据库状态同步(取决于配置的刷新模式),因此,直到发出flush或commit命令之前,都不会引发任何异常。因此,您可以尝试调用.saveAndFlush()
来强制执行数据库同步。这样,异常将立即引发。
为了进一步理解Spring如何处理事务管理,我将留下一个有用的链接:Transaction Management