第 14 章 持久化
14.1. 标准环境配置
这一节描述了环境如何配置 来在标准Java环境中使用hibernate.
01 | 02 |03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 |19 | 20 | 21 | 22 | 23 | 24 |25 |
line 04在流程引擎环境下指定了一个hibernate会话。 这意味着hibernate会话工厂会被延迟创建, 当它第一次需要时, 会缓存到EnvironmentFacTory中。
一个hibernate会话工厂在一个hibernate配置中 通过调用buildSessionFacTory()方法创建。 默认 情况下,hibernate配置会根据类型进行查找。
line 05指定一个hibernate配置。
line 06指定资源文件 hibernate.properties应该被加载到配置中。
line 07 – 13指定映射资源文件。
line 14 – 15提供一个单独的地方来指定 hibernate缓存策略,为所有的PVM类和集合。
line 20指定一个标准事务。 这是一个非常简单的全局事务策略, 没有可以用在标准环境下的恢复, 会获得所有或没有符合语义的多个事务型资源之上。
line 21指定hibernate会话, 会自动注册它自己,使用标准事务。
line 22指定一个PvmDbSession. 那是一个类,添加了方法绑定到特定的查询, 将在hiberante会话中 执行。
14.2. 标准hibernate配置
这儿是一系列的默认配置, 来在标准Java环境下和hsqldb一起配置hibernate.
hibernate.dialect org.hibernate.dialect.HSQLDialecthibernate.connection.driver_class org.hsqldb.jdbcDriverhibernate.connection.url jdbc:hsqldb:mem:.hibernate.connection.username sahibernate.connection.passwordhibernate.cache.use_second_level_cache truehibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider
在开发中可以选择数据库结构导出, 在会话工厂创建的时候创建数据库结构, 在会话工厂关闭的时 候删除数据库结构。
hibernate.hbm2ddl.auto create-drop
为了了解更多关于hibernate配置, 可以参考hibernate引用手册。
14.3. 标准事务
默认情况下,会使用 session.beginTransaction()启动hibernate事 务。 然后hibernate事务会封装成一个 org.jbpm.pvm.internal.hibernate.HibernateTransactionResource 资源被支持在 (org.jbpm.tx.StandardTransaction)。
在环境块内部,通过environment.getTransaction() 获得事务。所以在环境块内,事务可以通过 environment.getTransaction()。setRollbackOnly() 回滚。
当初创建时,标准事务会把自己注册, 在环境关闭时会被提醒。所以在关闭时, 标准事务会提交或 回滚 根据是否地调用了setRollbackOnly()。
所以在上面的配置中,每个环境块会拥有独立的事务。 至少,如果使用的是hibernate会话。
14.4. 流程实例化的基础
在下个例子中,我们将演示hibernate持久化是如何使用在 一个具体例子中的。’persistent process’是一个简单的 三步流程:
图 14.1. 持久化流程
三个活动会是等待状态, 就像第 5.4 节 “ExternalActivity实例”。
为了确认我们持久化了这个类,我们为它创建了hibernate映射, 并像这样把它添加到配置文件中:
下一个代码片段演示了一个单元测试方法的内容。 这个方法首先创建环境工厂,然后,在第一个事务 中, 一个流程定义会被创建, 并保存到数据库。然后第二个事务会创建这那个流程的一个新执行。 下 面的两个事物会向执行提供外部触发器。
EnvironmentFacTory environmentFacTory = EnvironmentFacTory.parse(new ResourceStreamSource( "org/jbpm/examples/ch09/environment.cfg.xml"));
然后在第一个事务中,一个流程被创建了,并保存到数据库中。 这是一个通常的引用,像是发布一个 流程, 它只需要执行一次。
Environment environment = environmentFacTory.openEnvironment();try { PvmDbSession pvmDbSession = environment.get(PvmDbSession.class); ProcessDefinition processDefinition = ProcessFacTory.build("persisted process") .activity ("one").initial().behaviour(new State()) .transition().to("two") .activity("two").behaviour(new State()) .transition().to("three") .activity("three").behaviour(new State()) .done(); pvmDbSession.save (processDefinition);} finally { environment.close();}
在前一个事务中,流程定义,活动,转移 会被插入到数据库表中。
接下来我们演示一个流程定义的新流程执行是如何启动的。 注意在这个情况下,我们提供了一个业务 键 叫做’first’.这会让我们更简单的处理相同的执行 从数据库的事务中。在启动新流程执行后, 它会 等待’one’活动 因为行为是一个等待状态。
environment = environmentFacTory.openEnvironment();try { PvmDbSession pvmDbSession = environment.get(PvmDbSession.class); ProcessDefinition processDefinition = pvmDbSession.findProcessDefinition("persisted process"); assertNotNull(processDefinition); Execution execution = processDefinition.startExecution("first"); assertEquals("one", execution.getActivity ().getName()); pvmDbSession.save(execution);} finally { environment.close();}
在上一个事务中,一个新执行记录会被插入到 数据库中。
下一步,我们反馈一个外部触发器到这个存在的流程执行中。 我们读取执行,提供一个signal,然后 只是把它保存回数据库中。
environment = environmentFacTory.openEnvironment();try { PvmDbSession pvmDbSession = environment.get(PvmDbSession.class); Execution execution = pvmDbSession.findExecution("persisted process", "first"); assertNotNull (execution); assertEquals("one", execution.getActivity().getName()); // external trigger that will cause the execution to execute until // it reaches the next wait state execution.signal(); assertEquals("two", execution.getActivity ().getName()); pvmDbSession.save(execution);} finally { environment.close();}
前一个事务会对已存在的执行进行更新, 重新分配外键,引用活动表中的 另一条记录。
UPDATE JBPM_EXECUTIONSET NODE_=?, DBVERSION_=?, ...WHERE DBID_=? AND DBVERSION_=?
SQL中的版本,显示了自动乐观锁,加入了PVM持久化中 所以流程持久化可以很容易 在多JVM或多机器 环境下使用。
在实例代码中,这里又有一个事务,它与前一个事务 完全相同,从’two’活动到’three’活动 获得了 执行。
所有这个展示了PVM可以在事务中从一个等待状态移动到 另一个等待状态。每个事务对应 一个状态转 移。
注意在自动活动的情况下,多个活动会在执行 到达一个等待状态前被执行。 一般来说这是期望的行 为。一旦自动活动消耗太长时间, 你不希望阻塞原始事务,等待这些自动活动的完成, 参考??? 来 获得它可以如何在流程定义之间将事务划分界限, 这也可以看做是一个流程执行过程中的安全点。
14.5. 业务键
TODO
TODO: 常规的持久化架构
TODO: 对象引用
TODO: 线程,通过分支和结合实现同步
TODO: 缓存
TODO: 流程实例迁移
于是夜莺会在黎明到来之前勇敢的将胸膛顶住蔷薇的刺,