乐观锁概念:当两人同时修改同一条记录时,后提交者会得到lockException异常,表示对象被其他人修改过,这个锁不会产生死锁,而且业务上不会存在影响,所以叫乐观锁。
在FoxBPM系统中针对流程操作可能会存在数据并发操作,那么针对流程操作中就要考虑如何避免这样场景发生。下面就介绍FoxBPM中实现乐关锁功能;
HasRevision接口(凡是实现HasRevision接口的对象,都表示添加了乐观锁控制)
package org.foxbpm.engine.db; /** * @author kenshin * */ public interface HasRevision { void setRevision(int revision); int getRevision(); int getRevisionNext(); }
下面以Token 表介绍:
1、首先Token表中添加REV_字段
2、在Token.xml文件insert标签中加默认值1
<insert id="insertToken" parameterType="org.foxbpm.engine.impl.entity.TokenEntity" > insert into ${prefix}_run_token (ID, NAME, PROCESSINSTANCE_ID, NODE_ID, PARENT_ID, START_TIME, END_TIME, NODEENTER_TIME, ARCHIVE_TIME, ISSUSPENDED, ISLOCK, ISACTIVE, ISSUBPROCESSROOTTOKEN,LOOP_COUNT,REV_) values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{processInstanceId,jdbcType=VARCHAR}, #{nodeId,jdbcType=VARCHAR}, #{parentId,jdbcType=VARCHAR}, #{startTime,jdbcType=TIMESTAMP}, #{endTime,jdbcType=TIMESTAMP}, #{nodeEnterTime,jdbcType=TIMESTAMP}, #{archiveTime,jdbcType=TIMESTAMP}, #{isSuspended,jdbcType=VARCHAR}, #{isLocked,jdbcType=VARCHAR}, #{isActive,jdbcType=VARCHAR}, #{isSubProcessRootToken,jdbcType=VARCHAR},#{loopCount,jdbcType=INTEGER},1) </insert>
3、在update标签where条件中添加REV_ 判断和设置 REV_字段值。
<update id="updateToken" parameterType="org.foxbpm.engine.impl.entity.TokenEntity" > update ${prefix}_run_token set NAME = #{name,jdbcType=VARCHAR}, PROCESSINSTANCE_ID = #{processInstanceId,jdbcType=VARCHAR}, NODE_ID = #{nodeId,jdbcType=VARCHAR}, PARENT_ID = #{parentId,jdbcType=VARCHAR}, START_TIME = #{startTime,jdbcType=TIMESTAMP}, END_TIME = #{endTime,jdbcType=TIMESTAMP}, NODEENTER_TIME = #{nodeEnterTime,jdbcType=TIMESTAMP}, ARCHIVE_TIME = #{archiveTime,jdbcType=TIMESTAMP}, ISSUSPENDED = #{isSuspended,jdbcType=VARCHAR}, ISLOCK = #{isLocked,jdbcType=VARCHAR}, ISACTIVE = #{isActive,jdbcType=VARCHAR}, ISSUBPROCESSROOTTOKEN = #{isSubProcessRootToken,jdbcType=VARCHAR}, LOOP_COUNT=#{loopCount,jdbcType=INTEGER}, REV_ = #{revisionNext,jdbcType=INTEGER} where ID = #{id,jdbcType=VARCHAR} AND REV_ = #{revision,jdbcType=INTEGER} </update>
4、让TokenEntity类实现HasRevision接口并且实现所有方法
public void setRevision(int revision) { this.revision = revision; } public int getRevision() { return revision; } public int getRevisionNext() { return revision + 1; }
5、在数据更新时添加以下代码:
affectedRow = getSqlSession().update(updateStatement, updateObject); // 并发处理 if (updateObject instanceof HasRevision) { if (affectedRow != 1) { throw new FoxBPMOptimisticLockException("ID=" + updateObject.getId() + "记录已经被修改,当前禁止修改!"); } ((HasRevision) updateObject).setRevision(((HasRevision) updateObject).getRevisionNext()); }
上面代码首先处理实例数据更新,如果该实例实现HasRevision接口,那么就判断更新受影响的记录数是否不为1,如果不为1就说明记录已经被修改不能继续修改,否则就更新TokenEntity实例的版本值。
最后 关于“乐观锁”的介绍可以在网上搜索查阅。
有关FoxBPM了解请访问(https://github.com/FoxBPM)。