JBPM的持久化相關的概念主要包括以下幾點:JPA,JTA,Hibernate,JNDI
選擇Hibernate可以直接通過實體類,映射生成對應的數據庫表,因爲JBPM的工作引擎,很多中間狀態信息,對應的實體類都是JBPM設計好的,通過JPA或者Hibernate相關的註解標記,在運行時,會自動在數據庫上生成對應的表。方便快捷安全,因爲本來JBPM和JPA都是Jboss社區的,所以選擇JPA作爲持久化的方式也可以理解。
在你的項目中,比如我的是Springboot的項目:
注意在resources下的META-INF目錄下的persistence.xml這是JPA的持久化配置文件,如果沒有的話可以自己copy一份
內容如下
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd
http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistence-unit name="org.jbpm.persistence.jpa" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/jbpm-ds</jta-data-source>
<mapping-file>META-INF/JBPMorm.xml</mapping-file>
<class>org.drools.persistence.info.SessionInfo</class>
<class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
<class>org.drools.persistence.info.WorkItemInfo</class>
<class>org.jbpm.persistence.correlation.CorrelationKeyInfo</class>
<class>org.jbpm.persistence.correlation.CorrelationPropertyInfo</class>
<class>org.jbpm.runtime.manager.impl.jpa.ContextMappingInfo</class>
<class>org.jbpm.process.audit.ProcessInstanceLog</class>
<class>org.jbpm.process.audit.NodeInstanceLog</class>
<class>org.jbpm.process.audit.VariableInstanceLog</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.connection.release_mode" value="after_transaction"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>
</properties>
</persistence-unit>
</persistence>
按照JBPM官方的文檔持久化部分的描述的核心代碼如下(當然我自己改卡了一部分):
EntityManagerFactory emf =
Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa");
Environment env = EnvironmentFactory.newEnvironment();
env.set( EnvironmentName.ENTITY_MANAGER_FACTORY, emf );
// create a new KIE session that uses JPA to store the runtime state
KieHelper kieHelper = new KieHelper();
KieBase kbase = kieHelper.addResource(ResourceFactory.newClassPathResource("helloolsen.bpmn")).build();
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
int sessionId = ksession.getId();
// invoke methods on your method here
ksession.startProcess("business-application-kjar.helloolsen");
ksession.dispose();
這個“org.jbpm.persistence.jpa”我當時看矇蔽了,以爲是掃描這個路徑下相關的類或者包呢,但是一直報錯,我就去官網看文檔看了一眼這個persistence.xml文檔,我定睛一看,尼瑪的,
<persistence-unit name="org.jbpm.persistence.jpa" transaction-type="JTA">
好眼熟,原來對應的是這個name,剛開始這個name不是這樣子的,是默認的,忘了什麼了,就不管了
然後後面還是報,報什麼
jdbc/jbpm-ds
找不到,然後我就去查了一下那個標籤
<jta-data-source>,
不查不知道,一查原來這個persistence.xml的整個配置文件是JPA的配置文件,我還以爲是JBPM相關的文件呢,
然後又一看,你猜怎麼着,原來這個標籤裏面的內容是數據源(datasource)的名字,但是通過JNDI獲取的,然後我就去spring的配置文件裏面配置自己的數據源看能用不,配置如下:
spring.datasource.name=jdbc/jbpm-ds
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/jbpm
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
我以爲這樣配置了給個名字就行了誰知道這尼瑪不行,我就尋思着是不是還可以再起一個jndi-name什麼的,誰還沒個外號是吧,然後我去查springboot的配置文件,果然有:
spring.datasource.jndi-name=jdbc/jbpm-ds
再加上這個jndi-name,但是還是獲取不到jdbc/jbpm-ds,頭疼,然後我就看官網的描述,說在java環境中可以加上這樣的配置:
Properties driverProperties = new Properties();
driverProperties.put("user", "sa");
driverProperties.put("password", "sa");
driverProperties.put("url", "jdbc:h2:mem:jbpm-db;MVCC=true");
driverProperties.put("driverClassName", "org.h2.Driver");
driverProperties.put("className", "org.h2.jdbcx.JdbcDataSource");
PoolingDataSourceWrapper pdsw = DataSourceFactory.setupPoolingDataSource("jdbc/jbpm-ds", driverProperties);
我就懵逼了,這個pdsw配置到那裏去呢?從上面的java代碼裏,我看了每個方法都沒有添加數據源的地方,因爲在我們的常識中實例化了數據源對象一般這個數據源對象都會被一個環境相關的初始化對象set進去,然後加載持久化信息。
可是誰知道呢?我就把代碼copy進去試試
// configure datasource
Properties driverProperties = new Properties();
driverProperties.put("user", "root");
driverProperties.put("password", "123456");
driverProperties.put("url", "jdbc:mysql://localhost:3306/jbpm");
driverProperties.put("driverClassName", "com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
driverProperties.put("className", "com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
driverProperties.put("databaseName", "jbpm");
driverProperties.put("portNumber", "3306");
driverProperties.put("serverName", "localhost");
PoolingDataSourceWrapper pdsw = DataSourceFactory.setupPoolingDataSource("jdbc/jbpm-ds", driverProperties);
// create the entity manager factory and register it in the environment
EntityManagerFactory emf =
Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa.test");
Environment env = EnvironmentFactory.newEnvironment();
env.set( EnvironmentName.ENTITY_MANAGER_FACTORY, emf );
// create a new KIE session that uses JPA to store the runtime state
KieHelper kieHelper = new KieHelper();
KieBase kbase = kieHelper.addResource(ResourceFactory.newClassPathResource("helloolsen.bpmn")).build();
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
int sessionId = ksession.getId();
// invoke methods on your method here
ksession.startProcess("business-application-kjar.helloolsen");
ksession.dispose();
那個pdsw就像個孤兒一樣在哪放着了,看着實屬可憐,
但是還是報
jdbc/jbpm-ds
找不到,我是當時真得報這個錯誤了,如果你沒報那你可真幸運,然後我就換另外一種方式,
我知道數據源配置都可以在server的容器初始化的時候在配置文件裏配置就可以了,比如tomcat的conf/context.xml裏面配置這些數據源信息,然後就可以JNDI獲取,但是springboot是內嵌的tomcat也就是說沒有這個配置文件了,我就想起來可以自定義tomcat了,但是仍然失敗了,然後我就去看源碼了,根據源碼,然後就解決了,於是就變成了了這樣的結果:
Properties driverProperties = new Properties();
driverProperties.put("user", "root");
driverProperties.put("password", "123456");
driverProperties.put("url", "jdbc:mysql://localhost:3306/jbpm");
driverProperties.put("driverClassName", "com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
driverProperties.put("className", "com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
driverProperties.put("databaseName", "jbpm");
driverProperties.put("portNumber", "3306");
driverProperties.put("serverName", "localhost");
PoolingDataSourceWrapper pdsw = DataSourceFactory.setupPoolingDataSource("jdbc/jbpm-ds", driverProperties);
// create the entity manager factory and register it in the environment
EntityManagerFactory emf =
Persistence.createEntityManagerFactory( "org.jbpm.persistence.jpa.test");
Environment env = EnvironmentFactory.newEnvironment();
env.set( EnvironmentName.ENTITY_MANAGER_FACTORY, emf );
// create a new KIE session that uses JPA to store the runtime state
KieHelper kieHelper = new KieHelper();
KieBase kbase = kieHelper.addResource(ResourceFactory.newClassPathResource("helloolsen.bpmn")).build();
StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env );
int sessionId = ksession.getId();
// invoke methods on your method here
ksession.startProcess("business-application-kjar.helloolsen");
ksession.dispose();
注意那個
driverClassName 不能寫成com.mysql.jdbc.Driver這個是不對的要換成我代碼裏面那個XA的這個是支持XA事務的驅動器,感興趣可以去了解一下XA事務,還有分佈式事務什麼的
然後persistence.xml的最終形態是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd
http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistence-unit name="org.jbpm.persistence.jpa.test" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/jbpm-ds</jta-data-source>
<mapping-file>META-INF/JBPMorm.xml</mapping-file>
<class>org.drools.persistence.info.SessionInfo</class>
<class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
<class>org.drools.persistence.info.WorkItemInfo</class>
<class>org.jbpm.persistence.correlation.CorrelationKeyInfo</class>
<class>org.jbpm.persistence.correlation.CorrelationPropertyInfo</class>
<class>org.jbpm.runtime.manager.impl.jpa.ContextMappingInfo</class>
<class>org.jbpm.process.audit.ProcessInstanceLog</class>
<class>org.jbpm.process.audit.NodeInstanceLog</class>
<class>org.jbpm.process.audit.VariableInstanceLog</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.connection.release_mode" value="after_transaction"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>
</properties>
</persistence-unit>
</persistence>
再說一下各個部分,那個<class>標籤是對應的要持久化的實體,也就是說,在JBPM執行business process(也被人翻譯爲工作流)的過程中的這些類中的信息都會被存儲到數據庫裏面
<mapping-file>META-INF/JBPMorm.xml</mapping-file>
這個標籤那個文件是hibernate的映射配置文件具體是什麼文件可以自己查一下,有沒有都無所謂的,
後面的property是hibernate相關特性的配置,具體可以逐條瞭解一下,
hibernate.hbm2ddl.auto
這個就比較重要了,舉個例子如果你配置了value=update,那麼如果這個實體類對應的表在數據庫中不存在,他會根據在這個類上的註解自動在數據庫裏生成對應的表,並存儲這個類對應的對象在各個時刻的數據,
看到左側欄的表和中間面板裏面的數據了嗎?兄弟,就這樣了,有什麼問題可以留言