用切面的方式实现全局性的乐观锁

阅读更多

 

用切面的方式实现全局性的乐观锁

 

乐观锁的思路update的查询条件加version,update的时候version+1

 

用拦截器拦截ibatis的updat方法(不是我们业务中的update方法),在sql中加入version的操作

 

 @Override

public Object intercept(Invocation invocation) throws Throwable {

    if ((invocation.getArgs() != null) && (invocation.getArgs().length > 0) && (invocation.getArgs()[0] != null)
            && ((invocation.getArgs()[0] instanceof MappedStatement))) {

        MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
        Object obj = invocation.getArgs()[1];
        if (ms.getSqlCommandType() != SqlCommandType.UPDATE) {
            log.debug("非更新语句,不需要乐观锁!");
        } else {
            if (obj == null) {
                return invocation.proceed();
            }
            if (obj != null && obj.getClass().isAnnotationPresent(VersionIgnored.class)) { // 如果标明不需要乐观锁
return invocation.proceed();
            }
            Field field = getField(obj, "version");
            if (field == null) {
                throw new RuntimeException("乐观锁的控制的参数必须包含version字段,且是普通PO对象");
            }
            Integer version = (Integer) getFieldValue(obj, "version");
            Method versionSetter = obj.getClass().getMethod("setVersion", Integer.class);
            if(version == null || versionSetter == null){
              throw new RuntimeException("乐观锁的控制的参数必须包含version字段不能为null, setVersion方法保持public状态");
            }
            SqlSource sqlSource = ms.getSqlSource();
            BoundSql boundsql = sqlSource.getBoundSql(obj);
            String sql = boundsql.getSql();
            String sqlparts[] = sql.split("[wW][hH][Ee][Rr][Ee]");
            String newsql;
            newsql = sqlparts[0] + ",version=version+1  where" + sqlparts[1] + " and version=" + version;
            BoundSql myBoundSql = new BoundSql(ms.getConfiguration(), newsql, boundsql.getParameterMappings(),
                    boundsql.getParameterObject());

            MappedStatement newms = copyFromMappedStatement(ms, new MyBoundSqlSource(myBoundSql));
            invocation.getArgs()[0] = newms;
            Object num = invocation.proceed();
            if (num != null && !"1".equals(num.toString())) {
                throw new RuntimeException("乐观锁版本不对");
            }
            versionSetter.invoke(obj, version + 1);
            return num;
        }
        return invocation.proceed();
    } else {
        return invocation.proceed();
    }
}
  • OptimisticLockInterceptor.zip (2.1 KB)
  • 下载次数: 0

你可能感兴趣的:(架构)