Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用JPA在Spring中进行事务处理和回滚_Java_Hibernate_Spring_Jpa 2.0_Java Ee 6 - Fatal编程技术网

Java 使用JPA在Spring中进行事务处理和回滚

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

嗨,StackOverflow的朋友们, 我不明白如何回滚我读过的Spring文档,但我仍然不明白。基本上,我将一直在db中保存一个对象(手动使用主键),好吧,对象被插入到db中。但是,当您使用相同的主键再次持久化该对象时,我导致了一个异常,这是正确的,违反了对唯一性的限制。在这种情况下,我将得到一个事务回滚,并警告您存在问题,然后继续运行该程序

这是我的班级:

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();
}
这是一个非常糟糕的做法。不要捕获异常,而是让它从方法中弹出。这样:

  • 事务划分机制将拦截异常并将事务标记为仅回滚
  • 您不会忽略异常(是的,捕获和记录几乎和吞咽一样糟糕)
  • 很可能会在更高级别捕获异常并正确记录(使用SLF4J或类似工具),而您将没有此样板文件
  • 长话短说:

    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();
    }
    
    这是一个非常糟糕的做法。不要捕获异常,而是让它从方法中弹出。这样:

  • 事务划分机制将拦截异常并将事务标记为仅回滚
  • 您不会忽略异常(是的,捕获和记录几乎和吞咽一样糟糕)
  • 很可能会在更高级别捕获异常并正确记录(使用SLF4J或类似工具),而您将没有此样板文件
  • 长话短说:

    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