一、引言

先来看一段SQLException

### Error updating database.  Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 事务(进程 ID 271)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。

由于公司db工程师的建议,针对sqlserver的查询语句尽量添加上with(nolock)来解决上述事务死锁问题;
针对db工程师的建议,如何通过扩展baseMapper,添加一些自定义的查询方法呢?我们以方法如下

二、自定义方法实现

步骤1.继承抽象的注入方法类

/***
 * 针对sqlserver增加with(nolock) 防止事务死锁
 */
public class SelectByIdNoLockMethod extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sql = "SELECT %s FROM %s with(nolock) WHERE %s=#{%s} %s";
        String method = "selectByIdNoLock";
        SqlSource sqlSource = new RawSqlSource(configuration, String.format(sql,
                sqlSelectColumns(tableInfo, false),
                tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
                tableInfo.getLogicDeleteSql(true, true)), Object.class);
        return addSelectMappedStatementForTable(mapperClass, method, sqlSource, tableInfo);
    }
}

步骤2.创建注入器,把自定义方法添加到集合当中。

@Component
public class MySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        // 添加自定义方法类
        methodList.add(new SelectByIdNoLockMethod());
        return methodList;
    }
}

步骤3.新建一个自定义的Mapper接口继承baseMapper接口,并添加我们扩展的查询

public interface MyMapper<T> extends BaseMapper<T> {

    /**
     * 自定义通用方法
     * @return
     */
    T selectByIdNoLock(Serializable id);
}

三、结尾

接下来直接调用就可以发现自动添加了with(nolock)关键字

public interface BusCommonFileLogMapper extends MyMapper<BusCommonFileLog> {

}
@Test
    public void selectByIdNoLock() {
        busCommonFileLogMapper.selectByIdNoLock("1465926655269212162");
    }

使用Mybatis Log Plugin 插件查看打印出来的sql就可以发现已经自动加上with(nolock)关键字啦
在这里插入图片描述

四、注意事项

由于是在启动时一次性注入的,所以没办法判断当前数据源,所以使用时需谨慎,只有在支持with(nolock)语法的数据库才能使用

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐