我有以下情况。我在spring使用JPA:
@Autowired SampleService service; @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void PerformLogic(LogicData data) throws SIASFaultMessage { SampleObject so = createSampleObject(); try{ .//do some logic to persist things in data . . persistData(data); . . . updateSampleObject(so); } catch(Exception){ updateSampleObject(so); throw new SIASFaultMessage(); } } @Transactional(propagation = Propagation.REQUIRES_NEW) public createSampleObject() { SampleObject so = new SampleObject(); . .//initialize so . service.persist(so); return so; } @Transactional(propagation = Propagation.REQUIRES_NEW) public updateSampleObject(SampleObject so) { service.persist(so); return so; }
当一切正常时,数据可以毫无问题地保存在数据库中。但是,当引发异常时,我需要方法 updateSampleObject(so) 将信息保留在数据库中。这不是正在发生的事情。如果抛出异常,方法 updateSampleObject也 将回滚,这不是我所需要的。我需要这两个方法( createSampleObject 和 updateSampleObject )始终保持持久,无论是否引发异常。我该如何实现?
而且,如果我用以下方法 注释 方法 createSampleObject 和 updateSampleObject :
@Transactional(propagation = Propagation.NEVER)
想法是抛出异常,而我没有抛出异常。问题出在哪里?分析日志,我看到以下行:
org.springframework.orm.jpa.JpaTransactionManager ==> Creating new transaction with name [com.test.PerformLogic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT....
这表示已创建此事务,但我看不到其他事务的任何提示。
这是我的Spring配置文件中有关事务的一部分
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="packagesToScan" value="cu.jpa"/> <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">${hdm2ddl.auto}</prop> </props> </property> <property value="/META-INF/jpa-persistence.xml" name="persistenceXmlLocation"/> <property name="persistenceUnitName" value="jpaPersistenceUnit"/> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="nestedTransactionAllowed" value="true" /> </bean> <tx:annotation-driven transaction-manager="transactionManager"/>
spring交易是基于代理的。因此,这是当bean A引起bean B事务时它如何工作的。A实际上具有对代理的引用,该代理委托给beanB。此代理是启动和提交/回滚事务的代理:
A ---> proxy ---> B
在您的代码中,A的事务方法调用了A的另一个事务方法。因此Spring无法拦截该调用并开始新的事务。这是一个常规方法调用,不涉及任何代理。
因此,如果要启动新事务,则该方法createSampleObject()应该在另一个bean中,并注入到当前bean中。
createSampleObject()
在文档中对此进行了更详细的说明。