mybatis实现乐观锁

背景:对于数据库的同一条记录,假若有两我的同时对数据进行了修改,而后最终同步到数据库的时候,由于存在着并发,产生的结果是不可预料的。最简单的解决方式就是经过给表的记录加一个version字段,记录在修改的时候须要比较一下version是否匹配,若是匹配就更新,不匹配就直接失败。更新成功则把version+1,也就是所谓的乐观锁。固然这样的逻辑最好能作到对开发人员透明,本插件就是来作这件事情的。java

1. 使用方式:在mybatis配置文件中加入以下配置,就完成了。
<plugins>
    <plugin interceptor="com.chrhc.mybatis.locker.interceptor.OptimisticLocker"/>
</plugins>sql

 

2. 对插件配置的说明:
上面对插件的配置默认数据库的乐观锁列对应的Java属性为version。这里能够自定义属性命,例如:
<plugins>
    <plugin interceptor="com.chrhc.mybatis.locker.interceptor.OptimisticLocker">
        <property name="versionColumn" value="xxx"/><!--数据库的列名-->
        <property name="versionField" value="xxx"/> <!--java字段名-->
    </plugin>
</plugins>数据库

 

3. 效果:
以前:update user set name = ?, password = ? where id = ?
以后:update user set name = ?, password = ?, version = version+1 where id = ? and version = ?mybatis

 

4. 对version的值的说明:
一、当PreparedStatement获取到version值以后,插件内部会自动自增1。
二、乐观锁的整个控制过程对用户而言是透明的,这和Hibernate的乐观锁很类似,用户不须要关心乐观锁的值。并发

 

5.插件原理描述:
插件经过拦截mybatis执行的update语句,在原有sql语句基础之上增长乐观锁标记,好比,原始sql为:
update user set name = ?, password = ? where id = ?,
那么用户不须要修改sql语句,在插件的帮助之下,会自动将上面的sql语句改写成为:
update user set name = ?, password = ?, version = version + 1 where id = ? and version = ?,
形式,用户也不用关心version先后值的问题,全部的动做对用户来讲是透明的,由插件本身完成这些功能。app

 

6.默认约定:
一、本插件拦截的update语句的Statement都是PreparedStatement,仅针对这种方式的sql有效;
二、mapper.xml的<update>标签必需要与接口Mapper的方法对应上,也就是使用mybatis推荐的方式,可是多个接口能够对应一个mapper.xml的<update>标签;
三、本插件不会对sql的结果作任何操做,sql自己应该返回什么就是什么;
四、插件默认拦截全部update语句,若是用户对某个update不但愿有乐观锁控制,那么在对应的mapper接口方法上面增长@VersionLocker(false)或者@VersionLocker(value = false),这样插件就不会对这个update作任何操做,等同于没有本插件;
五、本插件目前暂时不支持批量更新的乐观锁,缘由是因为批量更新在实际开发中应用场景很少,另外批量更新乐观锁开发难度比较大;
六、Mapper接口的参数类型必须和传入的实际类型保持一致,这是因为在JDK版本在JDK8如下没有任何方法能获取接口的参数列表名称,所以,插件内部是使用参数类型和参数做为映射来匹配方法签名的;spa