Java 使用JPA在Spring中进行事务处理和回滚
嗨,StackOverflow的朋友们, 我不明白如何回滚我读过的Spring文档,但我仍然不明白。基本上,我将一直在db中保存一个对象(手动使用主键),好吧,对象被插入到db中。但是,当您使用相同的主键再次持久化该对象时,我导致了一个异常,这是正确的,违反了对唯一性的限制。在这种情况下,我将得到一个事务回滚,并警告您存在问题,然后继续运行该程序 这是我的班级:Java 使用JPA在Spring中进行事务处理和回滚,java,hibernate,spring,jpa-2.0,java-ee-6,Java,Hibernate,Spring,Jpa 2.0,Java Ee 6,嗨,StackOverflow的朋友们, 我不明白如何回滚我读过的Spring文档,但我仍然不明白。基本上,我将一直在db中保存一个对象(手动使用主键),好吧,对象被插入到db中。但是,当您使用相同的主键再次持久化该对象时,我导致了一个异常,这是正确的,违反了对唯一性的限制。在这种情况下,我将得到一个事务回滚,并警告您存在问题,然后继续运行该程序 这是我的班级: public class ServiceDaoImpl{ @PersistenceContext (unitName="fb
public class ServiceDaoImpl{
@PersistenceContext (unitName="fb-persistence")
protected EntityManager em;
public void setEntityManager(EntityManager entityManager) {
this.em = entityManager;
}
@Transactional(readOnly=false)
public void write(Service entity){
try {
em.persist(entity);
em.flush();
} catch(Exception ex) {
ex.printStackTrace();
}
}
/*
* .. other method
*/
}
这是一堆错误:
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1214)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1147)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1153)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:798)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at $Proxy27.flush(Unknown Source)
at it.synclab.fb.jpa.dao.impl.GenericDaoImpl.write(GenericDaoImpl.java:236)
at it.synclab.fb.jpa.dao.impl.EnteDaoImpl.write(EnteDaoImpl.java:1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy34.write(Unknown Source)
at it.synclab.fb.jpa.test.ConfigTest.insertEnte(ConfigTest.java:47)
at it.synclab.fb.jpa.test.ConfigTest.main(ConfigTest.java:32)
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:795)
... 21 more
Caused by: java.sql.BatchUpdateException: ORA-00001: violata restrizione di unicità (FLUSSIBATCH.SYS_C008896)
我的配置文件是(persistence.xml和applicationContext.xml):
这是applicationContext.xml:
...
这是persistence.xml文件:
org.hibernate.ejb.HibernatePersistence
META-INF/orm.xml
it.entity.Service
真的
位于oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:629)
位于oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:9467)
位于oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:211)
位于org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
位于org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 还有27个
线程“main”org.springframework.transaction.TransactionSystemException中出现异常:无法提交JPA事务;嵌套异常为javax.persistence.RollbackException:标记为rollbackOnly的事务
位于org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:476)
位于org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
位于org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
位于org.springframework.transaction.interceptor.TransactionSpectSupport.commitTransactionAfterReturning(TransactionSpectSupport.java:393)
位于org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
位于org.springframework.aop.framework.ReflectiveMethodInvocation.procedue(ReflectiveMethodInvocation.java:172)
位于org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
位于$Proxy34.write(未知来源)
位于it.synclab.fb.jpa.test.ConfigTest.insertEnte(ConfigTest.java:47)
位于it.synclab.fb.jpa.test.ConfigTest.main(ConfigTest.java:32)
原因:javax.persistence.RollbackException:标记为rollbackOnly的事务
位于org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:73)
位于org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
... 9更多
为什么要这么复杂?我只是不明白。。。我希望你们中的一些人也遇到了同样的问题并解决了我不知道我是否正确理解了您的问题,但您的问题可能与
ServiceDaoImpl
异常处理有关:
try {
em.persist(entity);
em.flush();
} catch(Exception ex) {
ex.printStackTrace();
}
这是一个非常糟糕的做法。不要捕获异常,而是让它从方法中弹出。这样:
public class ServiceDaoImpl{
@PersistenceContext (unitName="fb-persistence")
private EntityManager em;
@Transactional(readOnly=false)
public void write(Service entity){
em.persist(entity);
em.flush();
}
}
请注意,
EntityManager
不需要setter,字段可以是私有的。我不知道我是否正确理解您的问题,但您的问题可能是ServiceDaoImpl
异常处理:
try {
em.persist(entity);
em.flush();
} catch(Exception ex) {
ex.printStackTrace();
}
这是一个非常糟糕的做法。不要捕获异常,而是让它从方法中弹出。这样:
public class ServiceDaoImpl{
@PersistenceContext (unitName="fb-persistence")
private EntityManager em;
@Transactional(readOnly=false)
public void write(Service entity){
em.persist(entity);
em.flush();
}
}
请注意,
EntityManager
不需要setter,字段可以是私有的。在写入方法中添加一个try-catch块,并在出错时抛出异常
如果要控制回滚事件,请在出现的异常的
@Transactional
注释中添加rollbackor
或rollbackorClassName
属性。在写入方法中添加一个try-catch块,并在出错时引发异常
如果您想控制回滚事件,请在您引发的异常的
@Transactional
注释中添加rollbackor
或rollbackorClassName
属性。这对他没有帮助,因为此方法从未引发异常(它正在被吞没)。是,他可以添加一个异常抛出并使用回滚类控制它,我编辑我的帖子ok,但如果我有另一种类型的异常将被吞没,正如正确指出的@tomasznurkiewicz,这对他没有帮助,因为该异常从未从该方法中抛出(它正在吞没)。是的,他可以添加一个异常抛出并使用回滚类控制它,因为我编辑了我的帖子,但如果我有另一种类型的异常将被吞没,正如正确指出的@TomaszNurkiewiczI wa