乐观锁概念:当两人同时修改同一条记录时,后提交者会得到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)。