Mybatis-Plus SQL注入器的使用

Mybatis-Plus SQL注入器

今天看Mybatis-plus官网发现了这个SQL注入器,感觉以后有机会用上,记录一手。

重要的话说前面:MP的官网确实不友好,但是他们将示例代码都放在了gitee上:https://gitee.com/baomidou/mybatis-plus-samples/tree/master/mybatis-plus-sample-deluxe.

Mybatis-Plus SQL注入器的使用_第1张图片

里面基本都有示例代码,可拉取下来找些博客对着看

两篇不错的博客:

参考:Mybatis-Plus的应用场景及注入SQL原理分析.

参考:Mybatis-Plus入门系列(11)- MybatisPlus之Sql注入器及源码分析.

SQL注入器是什么?

官网其实等于没说,这对我们这种小白来说非常不友好。大概就是MP的官方文档槽点如此多的原因。

说回正题,从字面意思理解:把SQL注入到某个地方。

SQL注入器的作用就是:你可以在Mapper层自定义方法,然后将SQL模板注入到MP中

注意,注入器和我们自定义方法+自己写sql.xml的区别:
使用SQL注入器,通常是使用自定义Mapper(MyBaseMapper)接口继承BaseMapper接口,我们自定义的方法就写在MyBaseMapper里。然后我们业务相关的Mapper继承MyBaseMapper就都可以使用该方法。这一切只需要我们自定义一个SQL模板,注入到MP即可,而不是换一个表就得重写一个xml

如何实现SQL注入器?

  1. 写一个方法类(就是你要定义的方法要有一个对应类,mp封装的每一个方法都要定义一个对应的类),在类中写SQL模板,需继承AbstractMethod类
  2. 写一个SQL注入类,将你定义的方法注入MP
  3. 写一个用于被继承的Mapper接口(比如MyBaseMapper),该接口需继承BaseMapper接口
  4. 写一个配置类,把我们写的注入类装进Spring容器
  5. 写你的业务Mapper层,继承自定义的MyBaseMapper

环境准备

利用springboot快速初始化项目,需要用到Mysql driver、spring web

plus依赖如下:


    com.baomidou
    mybatis-plus-boot-starter
    3.5.1

配置文件:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo_xp?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
//打印执行的sql
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

如果嫌构建项目结构繁琐,可以看看这篇plus代码生成器的使用:https://blog.csdn.net/qq_42682745/article/details/120626012

实现SQL注入器

在此说明,为了简单起见(我也不太会),我定义的方法名叫testxp(),功能是查询所有

1.写一个方法类,在类中写SQL模板,需继承AbstractMethod

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

public class Testxp extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) {
        /* 执行 SQL ,动态 SQL 参考类 SqlMethod */
        String sql = "select * from " + tableInfo.getTableName();

        /* mapper 接口方法名一致 */
        String method = "testxp";
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        // 查询方法对应addSelectMappedStatementForTable
        return addSelectMappedStatementForTable(mapperClass, method, sqlSource, tableInfo);
    }
}

其中SQL模板,官方示例的通过id查找是这样的:

String sql = "select * from " + tableInfo.getTableName()
        + " where " + tableInfo.getKeyColumn() + "=#{" + tableInfo.getKeyProperty() + "}";

所以SQL模板大概就是这样写的。


然后,就是你的返回类型了,定义的查询方法就找select的,删除方法就返回delete的
Mybatis-Plus SQL注入器的使用_第2张图片

2.写一个SQL注入类,将你定义的方法注入MP,继承DefaultSqlInjector就好了

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import com.baomidou.mybatisplus.extension.injector.methods.LogicDeleteByIdWithFill;

import java.util.List;

public class MySqlInjector extends DefaultSqlInjector {
    @Override
    public List getMethodList(Class mapperClass, TableInfo tableInfo) {
        List methodList = super.getMethodList(mapperClass, tableInfo);
        //增加自定义方法
        methodList.add(new Testxp());
        /**
         * 以下 3 个为内置选装件
         * 头 2 个支持字段筛选函数
         */
        // 例: 不要指定了 update 填充的字段
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        methodList.add(new AlwaysUpdateSomeColumnById());
        methodList.add(new LogicDeleteByIdWithFill());
        return methodList;
    }
}

在我们的MySqlInjector类里面,我们只需要改
Mybatis-Plus SQL注入器的使用_第3张图片

把第一步自定义的方法类放进去就好了,

至于下面的内置选装件,意思就是MP给你提供的”组件“类,你可以用也可以不用。看情况,这里我们就全都加上

3.写一个用于被继承的Mapper接口(比如MyBaseMapper)

public interface MyBaseMapper extends BaseMapper {
    List testxp();
}

需继承BaseMapper(当然测试阶段可以不继承BaseMapper,不继承意味着我们无法使用MP封装的方法),在接口中添加你自定义的方法,我这里就是testxp()

4.写一个配置类,把我们写的SQL注入类装进Spring容器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {
    
    @Bean
    public MySqlInjector sqlInjector() {
        return new MySqlInjector();
    }

}

5.写你的业务Mapper层,继承自定义的MyBaseMapper

@Mapper
@Repository
public interface BucketMapper extends MyBaseMapper {
    
}

6.写测试类或测试接口

@SpringBootTest
class BucketApplicationTests {

    @Autowired
    private BucketMapper bucketMapper;

    @Test
    void contextLoads() {
        List testxp = bucketMapper.testxp();
        for (Bucket bucket : testxp) {
            System.out.println(bucket);
        }
    }

}

大功告成!

谈谈它的优缺点:(仅学习过程的看法)

优点:不用重复写格式相同的sql,将方法注册到MP内部可直接调用

缺点:个人觉得,对于MP而言,基本的CRUD已经内置了,我们需要动手写SQL的地方往往是多表查询、条件分页,除此之外的情况并且还要经常用的很少见,可见SQL注入器的使用范围很小,感觉地位很低啊。因为配置SQL注入器还是挺麻烦的,封装的方法如果使用不多还是别搞

你可能感兴趣的:(Mybatis-Plus,sql,java,mybatis,plus)