使用activiti中有個很重要的問題就是需要保證事物的控制
activiti使用的是mybatis作為orm技術 封裝了一系列的操作數據庫操作 這也就是大家調用的api 操作的數據庫表都是activit自帶的數據表 一般情況下使用spring整合
activiti的事物是很強大的 但是往往就不能如願 因為公司使用的都是自己的框架不能利用spring來整合事物。
通過java程序來控制activiti的事物
activiti的事物依賴於TransactionFactory 在創建流程引擎ProcessEngine來指定事物工廠,其原因分析如下:
創建流程引擎: ProcessEngine processEngine = conf.buildProcessEngine() ;
conf為StandaloneProcessEngineConfiguration的對象其buildProcessEngine方法如下:
public ProcessEngine buildProcessEngine() { init(); return new ProcessEngineImpl(this); }
//調用init方法
protected void init() {
initHistoryLevel();
initExpressionManager();
initVariableTypes();
initBeans();
initFormEngines();
initFormTypes();
initScriptingEngines();
initBusinessCalendarManager();
initCommandContextFactory();
initTransactionContextFactory();
initCommandExecutors();
initServices();
initIdGenerator();
initDeployers();
initJobExecutor();
initMailScanner();
initDataSource();
initTransactionFactory();
initSqlSessionFactory();
initSessionFactories();
initJpa();
initDelegateInterceptor();
initEventHandlers();
}
其中初始化了很多信息,可以依次看看源碼 其中initTransactionFactory()方法代碼如下:
// myBatis SqlSessionFactory ////////////////////////////////////////////////
protected void initTransactionFactory() {
if (transactionFactory==null) {
if (transactionsExternallyManaged) {
transactionFactory = new ManagedTransactionFactory();
} else {
transactionFactory = new JdbcTransactionFactory();
}
}
}
其中transactionFactory為 protected TransactionFactory transactionFactory; 類中的屬性
由代碼可知 如果transactionFactory不為空則事物工廠為JdbcTransactionFactory的實例化對象
那么設置StandaloneProcessEngineConfiguration的transactionFactory的值為一JdbcTransactionFactory對象即可
代碼如下:創建一個servlet監聽器 在容器啟動的時候創建一個流程引擎 (需要配置web.xml文件)
/********************************************************************** * <pre> * FILE : MyServletListener.java * CLASS : MyServletListener * * AUTHOR : Liaokailin * * FUNCTION : * * * Contact: Sina L凱林
* *====================================================================== * CHANGE HISTORY LOG *---------------------------------------------------------------------- * MOD. NO.| DATE | NAME | REASON | CHANGE REQ. *---------------------------------------------------------------------- * |2014年1月17日|Liaokailin| Created | * DESCRIPTION: * </pre> ***********************************************************************/ package com.infodms.dms.actions; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.ProcessEngines; import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration; import com.infodms.dms.db.DBManager; import com.infodms.dms.utils.DmsActivitiTransactionFactory; public class MyServletListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { ProcessEngines.destroy(); } @Override public void contextInitialized(ServletContextEvent arg0) { StandaloneProcessEngineConfiguration conf = (StandaloneProcessEngineConfiguration) ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration(); conf.setDataSource(DBManager.getDataSource()).setDatabaseSchemaUpdate("true").setDbHistoryUsed(true) ; conf.setTransactionFactory(new DmsActivitiTransactionFactory()) ; ProcessEngine processEngine = conf.buildProcessEngine() ; } }
conf.setTransactionFactory(new DmsActivitiTransactionFactory()) ;設置事物
DmsActivitiTransactionFactory代碼如下:
/********************************************************************** * <pre> * FILE : DmsActivitiTransactionFactory.java * CLASS : DmsActivitiTransactionFactory * * AUTHOR : Liaokailin * * FUNCTION : * * * Contact: Sina L凱林
* *====================================================================== * CHANGE HISTORY LOG *---------------------------------------------------------------------- * MOD. NO.| DATE | NAME | REASON | CHANGE REQ. *---------------------------------------------------------------------- * |2014年1月21日|Liaokailin| Created | * DESCRIPTION: * </pre> ***********************************************************************/ package com.infodms.dms.utils; import java.sql.Connection; import java.util.Properties; import org.apache.ibatis.transaction.Transaction; import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; import com.infoservice.po3.core.context.DBService; public class DmsActivitiTransactionFactory extends JdbcTransactionFactory { @Override public Transaction newTransaction(Connection conn, boolean autoCommit) { System.out.println("開啟新的事物"); return new DmsActitiviTransaction(conn,autoCommit) ; //return (Transaction) DBService.getInstance().getTransaction() ; } @Override public void setProperties(Properties props) { super.setProperties(props); } }
DmsActitiviTransaction 代碼如下:
/********************************************************************** * <pre> * FILE : DmsActitiviTransaction.java * CLASS : DmsActitiviTransaction * * AUTHOR : Liaokailin * * FUNCTION : * * * Contact: Sina L凱林 * *====================================================================== * CHANGE HISTORY LOG *---------------------------------------------------------------------- * MOD. NO.| DATE | NAME | REASON | CHANGE REQ. *---------------------------------------------------------------------- * |2014年1月21日|Liaokailin| Created | * DESCRIPTION: * </pre> ***********************************************************************/ package com.infodms.dms.utils; import java.sql.Connection; import java.sql.SQLException; import org.apache.ibatis.transaction.jdbc.JdbcTransaction; import com.infodms.dms.db.DBManager; import com.infoservice.po3.core.context.DBService; public class DmsActitiviTransaction extends JdbcTransaction { private static Connection conn = null ; public DmsActitiviTransaction(Connection connection, boolean desiredAutoCommit) { //connection.setAutoCommit(desiredAutoCommit); super(connection, desiredAutoCommit); try { connection.setAutoCommit(desiredAutoCommit); } catch (SQLException e) { e.printStackTrace(); } } @Override public Connection getConnection() { /*DBService d = DBService.getInstance() ; d.loadConf("/DataAccessContext.xml"); return d.getConnection() ;*/ // return DBService.getInstance().getConnection() ; try { if(conn==null){ synchronized (DmsActitiviTransaction.class) { conn = DBManager.getConnection() ; } } return conn ; } catch (Exception e) { System.out.println("獲取鏈接失敗:"+e); return null ; } } @Override public void close() throws SQLException { /* if(conn!=null&&!conn.isClosed()){ conn.close(); }*/ System.out.println("activit:close()"); } @Override public void commit() throws SQLException { /*if(conn!=null&&!conn.isClosed()){ conn.commit(); }*/ System.out.println("activit:commit()"); } @Override protected void resetAutoCommit() { System.out.println("resetAutoCommit()"); /*try { if (conn != null && !conn.isClosed()) { conn.setAutoCommit(false); } } catch (SQLException e) { e.printStackTrace(); }*/ } @Override public void rollback() throws SQLException { /*if(conn!=null&&!conn.isClosed()){ conn.rollback(); }*/ System.out.println("activit:rollback()"); } @Override protected void setDesiredAutoCommit(boolean arg0) { System.out.println("setDesiredAutoCommit:"+arg0); } }
其中DBManager
/********************************************************************** * <pre> * FILE : DBManager.java * CLASS : DBManager * * AUTHOR : Liaokailin * * FUNCTION : * * * Contact: Sina L凱林 * *====================================================================== * CHANGE HISTORY LOG *---------------------------------------------------------------------- * MOD. NO.| DATE | NAME | REASON | CHANGE REQ. *---------------------------------------------------------------------- * |2014年1月22日|Liaokailin| Created | * DESCRIPTION: * </pre> ***********************************************************************/ package com.infodms.dms.db; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import com.infoservice.po3.core.context.DBInfo; public class DBManager { public static DataSource dataSource = null ; public static Connection conn = null ; public static DataSource getDataSource(){ if(dataSource==null){ synchronized (DBManager.class) { Resource resource = new ClassPathResource("/DataAccessContext.xml"); BeanFactory springBeanFactory = new XmlBeanFactory(resource); DBInfo dbInfo = ((DBInfo)springBeanFactory.getBean("DBInfo")); dataSource = (DataSource)springBeanFactory.getBean(dbInfo.getDefDataSource()); System.out.println("獲取數據源"); } }else{ System.out.println("默認數據源調用"); } return dataSource ; } public static Connection getConnection() throws SQLException{ if(conn!=null&&!conn.isClosed()){ System.out.println("獲取默認連接"); }else{ synchronized (DBManager.class) { System.out.println("獲取連接"); conn = getDataSource().getConnection() ; } } return conn ; } public static void startTransaction(Connection connection) throws SQLException { System.out.println("開啟事物"); connection.setAutoCommit(false); } public static void endTransaction(Connection connection) throws SQLException{ System.out.println("提交事物 "); connection.commit(); connection.setAutoCommit(true); } public static void rollBack(Connection connection) throws SQLException{ System.out.println("回滾事物"); connection.rollback(); } }
調用的使用DBManager就ok了