没有关于Activiti的任何内容被保存到数据库中。应用程序实体正在保存到数据库。下面依次是 springfile、persitence.xml 文件和测试用例。
使用 SQL Server 探查器,我看到一个单独的数据库事务正在为由 Activiti 引起的数据库交互启动,此外,我看到单独的事务正在回滚而不是提交。其他应用程序数据库交互正在另一个事务上发生,并且正在提交此特定事务。
- 我认为,根据我的配置,Activiti 数据库交互将发生在与应用程序其余部分相同的事务上。我已经多次浏览了我的配置文件和代码,但没有看到任何错误。任何想法为什么要为 Activiti 数据库交互启动单独的事务?
- 当然,前一项是关键问题。但是,了解为什么回滚该单独的事务也会很有趣?
弹簧文件 :
<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="ActivitiTrialDataSource" class="org.apache.commons.dbcp.BasicDataSource" >
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />
<property name="url" value="jdbc:jtds:sqlserver://localhost:1433/ActivitiTrial" />
<property name="username" value="ActivitiTrial" />
<property name="password" value="ActivitiTrial" />
<property name="defaultAutoCommit" value="false" />
<property name="initialSize" value="5" />
</bean>
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="ActivitiTrialDataSource" />
<property name="persistenceUnitName" value="ActivitiTrial"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- Activiti -->
<bean id="activitiDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<property name="targetDataSource" ref="ActivitiTrialDataSource" />
</bean>
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="databaseType" value="mssql" />
<property name="dataSource" ref="activitiDataSource" />
<property name="transactionsExternallyManaged" value="true" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="false" />
<property name="history" value="audit" />
<property name="jobExecutorActivate" value="false" />
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="activitiRepositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
<bean id="activitiRuntimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
<bean id="activitiTaskService" factory-bean="processEngine" factory-method="getTaskService" />
<bean id="activitiHistoryService" factory-bean="processEngine" factory-method="getHistoryService" />
<bean id="activitiManagementService" factory-bean="processEngine" factory-method="getManagementService" />
坚持.xml文件:
<persistence-unit name="ActivitiTrial">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.archive.autodetection" value="hbm,class"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.hbm2ddl.auto" value="none"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.ejb.metamodel.generation" value="disabled"/>
</properties>
</persistence-unit>
测试用例:
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback=false)
@ContextConfiguration({"classpath:/springApplicationContext.xml"})
public class TrialTest {
@Autowired
RepositoryService activitiRepositoryService;
@Autowired
RuntimeService activitiRuntimeService;
@Autowired
TaskService activitiTaskService;
@PersistenceContext(unitName="ActivitiTrial")
EntityManager entityManager;
@Test
@Transactional
public void trialTest() throws Exception {
long entryMilliseconds = new Date().getTime();
activitiRepositoryService.createDeployment().addClasspathResource("process-definitions/neville.bpmn20.xml").deploy();
ApplicationEntity applicationEntity1 = new ApplicationEntity();
applicationEntity1.name = "App entity 1";
applicationEntity1.createDate = new Date();
Session hibernateSessionBeforeActiviti = ((Session) entityManager.getDelegate());
entityManager.persist(applicationEntity1);
entityManager.flush();
Map<String, Object> processVariables = new HashMap<String, Object>();
processVariables.put("ApplicationEntityID", applicationEntity1.id);
ProcessInstance processInstance = activitiRuntimeService.startProcessInstanceByKey("neville", processVariables);
String processInstanceId = processInstance.getId();
Task userTask = activitiTaskService.createTaskQuery().processInstanceId(processInstanceId).list().get(0);
ApplicationEntity applicationEntity2 = new ApplicationEntity();
applicationEntity2.name = "App entity 2";
applicationEntity2.createDate = new Date();
Session hibernateSessionAfterActiviti = ((Session) entityManager.getDelegate());
entityManager.persist(applicationEntity2);
entityManager.flush();
System.out.println("Leaving trialTest() in : " + (new Date().getTime() - entryMilliseconds) + " milliseconds.");
}
}
我通过解决MyBatis(JDBC)和Hibernate(JPA)之间的冲突解决了这个问题:
您应该jpaVendorAdapter
属性添加到 Bean entityManagerFactory
:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="ActivitiTrialDataSource" />
<property name="persistenceUnitName" value="ActivitiTrial"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
有关更多详细信息,请参阅此问题的答案。
我已经浪费了很多时间试图将公共事务管理器传递给 Spring 和 Activiti - 但没有结果。没有完全回答您的问题的意思,但我希望它能为您节省一些时间
活动论坛:
- http://forums.activiti.org/content/activiti 不提交回滚
- http://forums.activiti.org/content/activitispringhibernate-common-transaction-manager
演示:
这些存储库说明 Activiti 不接受 jpa/hibernate 事务:
- https://github.com/JOLO-/activiti-jpa-spring-transaction-demo.git
- https://github.com/JOLO-/activiti-hibernate-spring-transaction-demo.git
您还可以看到演示 https://github.com/Activiti/Activiti(Activiti + Spring + Bitronix)它可能会有所帮助(我还没有时间检查它)。
附言
作为常见交易的替代方案,我看到了补偿事件。