概述

MybatisPlus是一款Mybatis增强工具,用于简化开发,提高效率。 它在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

官网

基本配置

Maven依赖

  • mybatis-plus
  • mysql驱动

数据源配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mp_db?characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

创建Mapper接口

第一步,创建Mapper接口继承BaseMapper接口。

BaseMapper提供了很多常用方法,我们不需要去自己编写Sql语句。(狂喜)

第二步,扫描包,也可以直接加上 @Mapper注解。

@MapperScan("cn.cagurzhan.mapper")

常用配置

表映射规则

  • 默认情况下:泛型指定的实体类类名就是表名。如果不一致需要自己配置。
  • 单独配置:entity实体类上加注解 @TableName("tb_user")
  • 全局表名前缀:
mybatis-plus:
  global-config:
    db-config:
      table-prefix: tb_

主键生成策略

  • 默认情况:基于雪花算法的自增id。

雪花算法(Snowflake)是一种生成分布式全局唯一ID的算法,生成的ID称为Snowflake IDs或snowflakes。 这种算法由Twitter创建,并用于推文的ID。

  • 实体类的属性(对应表的字段):加上注解 @TableId(type=IdType.AUTO)

    • IdType的取值如下:
    • AUTO:数据库ID自增。依赖于数据库。
    • NONE:根据主键全局策略自动生成。
    • INPUT:手动设置主键。 不设置,插入的时候主键是null
    • ASSIGN_ID:当实体类主键属性为空,才会填充。使用雪花算法。
    • ASSIGN_UUID:当实体类主键属性为空,才会填充,使用UUID。
  • 全局设置:

mybatis-plus:
  global-config:
    db-config:
      # id生成策略 auto为数据库自增
      id-type: auto

字段映射

  • 默认:根据实体类属性名映射表中的字段名。
  • 如果不一致:字段上加上注解 @TableField(value="")

字段和列名驼峰映射

  • **默认开启!**形式:Java中userName -- Sql中 user_name
  • 关闭:
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: false

日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

核心方法

基本使用

  • 插入:mapper.insert(实体类)
  • 删除:mapper.deleteXXX()
    • 可以是BatchIds,传入id的集合。
    • 可以是单个Id
    • 可以是Map
  • 更新:mapper.updateXXX(实体类)
    • 可以是Id
    • 可以是实体类

条件构造器

条件构造器Wrapper可以帮助我们方便的构造条件。

UML图

UML图

  • AbstractWrapper提供了用来构造 where的方法。
    • QueryWrapper子类提供针对 select的语法。
    • UpdateWrapper子类提供针对 set的语法。
  • 方法文档:方法文档
    • 包括eq、lte、gt、gte、like、between、notLike等等。

演示AbstractWrapper方法

默认用AND连接。

//and
QueryWrapper wrapper = new QueryWrapper();
wrapper.gt("age",18);
wrapper.eq("address","四川成都");
wrapper.in("id",1,2,3); 
wrapper.between("like",10,29);
wrapper.like("name","Zhan"); //%Zhan%
wrapper.orderByDesc("age"); //降序
List<User> users = userMapper.selectList(wrapper);

演示QueryWrapper方法

  • select(要查询的列们)
  • select(实体类.class, Predicate)
  • select(Predicate)
//第一种
wrapper.select("id","user_name");
List<User>users = mapper.selectList(wrapper);

//第二种
wrapper.select(User.class,new Predicate<TableFieldInfo>(){
  public boolean test(TableFieldInfo info){
    return "user_name".equals(info.getColumn());
  }

});
mapper.selectList(wrapper);

//第三种
queryWrapper.select(new Predicate<TableFieldInfo>() {
    @Override
    public boolean test(TableFieldInfo tableFieldInfo) {
        return !"address".equals(tableFieldInfo.getColumn());
    }
});

演示UpdateMapper方法

前面的update需要传入一个实体类,如果修改的列比较少,创建这样一个对象显得有点麻烦和复杂。

好消息,好消息,UpdateWrapper提供了set方法来设置要更新的列及其值。

//把id大于1的用户年龄改为99
uwrapper.gt("id",1);
uwrapper.set("age",99);
mapper.update(null,uwrapper);

Lambda条件构造器

前面的条件构造器都是用字符串来确定列名,这种方式有一个弊端: 无法在编译期确定列名的合法性。

Lambda条件构造器:直接以实体类的方法引用的形式来指定列名。

方法引用语法见jdk8函数式编程新特性。

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge,18);
wrapper.eq(User::getAddress,"成都");
mapper.selectList(wrapper);

自定义SQL

复杂的SQL需要我们自己来定义方法,写对应的SQL。

Mybatis方式

  • 第一步,Mapper接口中定义方法。
    • 比如:User findUser(Long id)
  • 第二步,创建XML。
    • resources/mapper
    • 先配置XML文件存放目录。
mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml
  • 第三步,XML文件中映射文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.cagurzhan.mpdemo3.mapper.UserMapper">
    <select id="findMyUser" resultType="cn.cagurzhan.mpdemo3.domain.User">
        select * from tb_user where id=#{id}
    </select>
</mapper>

mybatis方式集合wrapper

  • 第一步,添加Wrapper类型参数的方法。

    • 注解是为了在xml中获取名字,Constants.WRAPPER就是:ew。
    • User findUserByWrapper(@param(Constants.WRAPPER) Wrapper<User> wrapper)
  • XML

    <select id="findMyUserByWrapper" resultType="cn.cagurzhan.mpdemo3.domain.User">
        select * from tb_user ${ew.customSqlSegment}
    </select>

分页查询

基本分页查询

配置分页查询拦截器

  • 创建 cn.cagurzhan.mpdemo.config.MybatisPlusConfig
@Configuration
public class PageConfig {
   @Bean
   public MybatisPlusInterceptor mybatisPlusInterceptor(){
       MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
       mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
       return mybatisPlusInterceptor;
   }
}

分页查询

IPage<User> page = new Page<>();
//每页条数
page.setSize(2);
//查询第几页
page.setCurrent(1);

mapper.selectPage(page,null);
//可以使用方法获得页数的数据
page.getRecord();//获取当前页数据
page.getTotal();//获取总记录数
page.getCurrent();//获得当前页数

多表分页查询

多表分页查询需要在mapper中自定义方法,方法参数是Page。其它的交给mybatis吧!

  • 第一步,定义接口中的方法
IPage<Orders> findAllOrders(Page<Orders> page);
  • 第二步,XML中写SQL
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sangeng.mapper.OrdersMapper">
    <select id="findAllOrders" resultType="cn.cagurzhan.mpdemo3.domain.Orders">
        SELECT
            o.*,u.user_name
        FROM
            tb_user u
                JOIN
            tb_orders o
            ON
                u.id = o.user_id
    </select>
</mapper>

Service层接口

Mp提供了Service层的实现,只需要编写接口继承IService,再创建一个接口实现类继承ServiceImpl,即可享用。

Service层支持了更多的批量操作方法。

  • 之前:需要自己在service中注入mapper。
  • 改造后:
//服务类接口
public interface UserService extends IService<User>{

}
//实现类
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{

}
//测试,直接调用service的方法
service.list();

自定义方法

其它的mapper需要自己注入再使用。

代码生成器

配置

  • 依赖
    • mybatis-plus-generator
    • freemaker
  • 生成器配置
public class GeneratorTest {
	@Test
	public void generate() {
		AutoGenerator generator = new AutoGenerator();

		// 全局配置
		GlobalConfig config = new GlobalConfig();
		String projectPath = System.getProperty("user.dir");
		// 设置输出到的目录
		config.setOutputDir(projectPath + "/src/main/java");
		config.setAuthor("cagur");
		// 生成结束后是否打开文件夹
		config.setOpen(false);

		// 全局配置添加到 generator 上
		generator.setGlobalConfig(config);

		// 数据源配置
		DataSourceConfig dataSourceConfig = new DataSourceConfig();
		dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mp_db?characterEncoding=utf-8&serverTimezone=UTC");
		dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
		dataSourceConfig.setUsername("root");
		dataSourceConfig.setPassword("root");

		// 数据源配置添加到 generator
		generator.setDataSource(dataSourceConfig);

		// 包配置, 生成的代码放在哪个包下
		PackageConfig packageConfig = new PackageConfig();
		packageConfig.setParent("cn.cagurzhan.mp.generator");

		// 包配置添加到 generator
		generator.setPackageInfo(packageConfig);

		// 策略配置
		StrategyConfig strategyConfig = new StrategyConfig();
		// 下划线驼峰命名转换
		strategyConfig.setNaming(NamingStrategy.underline_to_camel);
		strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
		// 开启lombok
		strategyConfig.setEntityLombokModel(true);
		// 开启RestController
		strategyConfig.setRestControllerStyle(true);
		generator.setStrategy(strategyConfig);
		generator.setTemplateEngine(new FreemarkerTemplateEngine());

        // 开始生成
		generator.execute();
	}
}