mybatisplus乐观锁不好使;mybatisplus使用乐观锁不查询直接生效

最近用myabtisplus比较多,发现其中的乐观锁必须查询才可以生效,原理是这样的:

1.如果不是update的方法直接返回:

if (SqlCommandType.UPDATE != ms.getSqlCommandType()) {
    return;
}

2.把参数转化为map并得到entity的class对象:

Map<String, Object> map = (Map<String, Object>) parameter;
Object et = map.getOrDefault(Constants.ENTITY, null);

备注:parameter中有两种参数,一种是et一种是ew,et对应的事update(Entity et),通过这种方式的update可以直接将参数封装为其Entity的Class对象,还有一种是ew,当使用QueryWrapper或者lamdaUpdate的时候会封装为ew,因为这两种方式传来的其实只是一个参数不是完整的对象,所以mp无法找到其中的version属性,自然也就无法去实现乐观锁,所以目前看来只有存在entity的时候才可以乐观锁.

所以原理知道了,在update之前必须先查一下才能得到version,然后update的时候在注入进去,本文要说的是不去查一下,因为这边代码已经写了2天了都去弄一下很麻烦~

方法也很简单,就是在其乐观锁插件外包一层提前去查一下并且注入进去就行了:

@Component
public class MyOptimisticLockerInterceptor extends OptimisticLockerInnerInterceptor {

    @Override
    public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        return false;
    }

    @Override
    public void beforeUpdate(Executor executor, MappedStatement ms, Object parameter) throws SQLException {
        try {
            if (SqlCommandType.UPDATE != ms.getSqlCommandType()) {
                return;
            }
            if (parameter instanceof Map) {
                Map<String, Object> map = (Map<String, Object>) parameter;
//获得参数的entity的CLass对象
                Object et = map.getOrDefault(Constants.ENTITY, null);
                Object id = null;
                Field etversionField=null;
                if(et==null){
//如果是ew方式没有Entity则强行取id,这里可以忽略不计
                    /*AbstractWrapper<?, ?, ?> aw = (AbstractWrapper<?, ?, ?>) map.getOrDefault(Constants.WRAPPER, null);
                    String sqlSegment = aw.getExpression().getSqlSegment();
                    String idSegment = sqlSegment.substring(sqlSegment.indexOf("id = #{ew.paramNameValuePairs.") + 30, sqlSegment.indexOf("id = #{ew.paramNameValuePairs.") + 39);
                    id = aw.getParamNameValuePairs().get(idSegment);*/
                }else{

                    TableInfo ettableInfo = TableInfoHelper.getTableInfo(et.getClass());
                    if (ettableInfo == null || !ettableInfo.isWithVersion()) {
                        return;
                    }
                    TableFieldInfo etfieldInfo = ettableInfo.getVersionFieldInfo();
                    etversionField = etfieldInfo.getField();
                    Field idFiled = et.getClass().getDeclaredField("id");
                    idFiled.setAccessible(true);
                    id = idFiled.get(et);
                }
//获得当前confuguration
                Configuration configuration1 = ms.getConfiguration();
                //Configuration configuration = GlobalConfigUtils.currentSessionFactory(et.getClass()).getConfiguration();
//获得mapper完整路径
                String pNameRef = ms.getId();
//获得包名
                String pName = pNameRef.substring(0,pNameRef.lastIndexOf(".")+1);
//封装一个查询命令
                MappedStatement ms2 = configuration1.getMappedStatement(pName+"selectById");
                /*TableInfo tableInfo = TableInfoHelper.getTableInfo(et.getClass());
                TableFieldInfo idFieldInfo = tableInfo.getFieldList().stream().filter(x -> x.getProperty().equals("id")).findFirst().get();
                Object id = idFieldInfo.getField().get(et);*/
//执行查询,查到version
                List<Object> query = executor.query(ms2, id, new RowBounds(), Executor.NO_RESULT_HANDLER);
                if(!CollectionUtils.isEmpty(query)){
                    Object obj = query.get(0);
                    TableInfo tableInfo = TableInfoHelper.getTableInfo(obj.getClass());
                    if (tableInfo == null || !tableInfo.isWithVersion()) {
                        return;
                    }
                    TableFieldInfo fieldInfo = tableInfo.getVersionFieldInfo();
                    Field versionField = fieldInfo.getField();
                    Object versionVal = versionField.get(obj);
//注入version
                    etversionField.set(et,versionVal);
//继续乐观锁
                    doOptimisticLocker(map, ms.getId());
                }
            }
            //super.beforeUpdate(executor, ms, parameter);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

将这个MyOptimisticLockerInterceptor代替原来的OptimisticLockerInnerInterceptor就可以了,后面在方法中直接update就可以实现乐观锁了,但是需要注意的是这里依然使用的mp原来的实现方法只不过提前省却了提前获得对象的过程所以mp的不能少,然后这里并没有解决lamdaUpdate无法乐观锁的问题,因为其本质是无法获取到Entity,如果想解决比较蠢得方式就是我上面注释的那样,强行获取到id然后查出来,然后修改时也强行加进去.

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值