栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mybatis-Plus使用全解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mybatis-Plus使用全解

前言

之前写了《SpringBoot | 第九章:Mybatis-plus的集成和使用》一文,只是简单的使用条件构造器列举了一些通用的CURD操作。本人也想写一篇通用的关于mybatis-plus的使用示例,一方面也让自己更加了解mybatis和mybatis-plus,另一方面,也因为很多新人刚入职公司时,对这块不是很熟悉,会有一些疑惑。所以,总的来说还是作为一份资产,可供人查阅,这样也能减少了很多的沟通成本。


所以本章节,就主要来讲解下关于Mybatis-plus的不同场景的用法,目前主要想到的是以下几个知识点,也是很常用的知识点了,后面有补充的会再启章节来记录的。另外,官网的文档已经很详尽了,大家可认真查阅下。

  1. 代码生成器
  2. 通用的CURD
  3. 条件构造器
  4. 自定义SQL语句
  5. 分页插件、性能分析插件
  6. 公共字段自动填充

工程准备

这里还是以**user表为例子,数据库为mysql**

DROp TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) DEFAULT NULL COMMENT '唯一标示',
  `code` varchar(20) DEFAULT NULL COMMENT '编码',
  `name` varchar(64) DEFAULT NULL COMMENT '名称',
  `status` char(1) DEFAULT '1' COMMENT '状态 1启用 0 停用',
  `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

关于SpringBoot和Mybatis-plus的集成,这里就不阐述了,这个不是今天的重点。不熟悉的同学,可移步:http://blog.lqdev.cn/2018/07/21/springboot/chapter-nine/进行查看了解。

代码生成器

Mybatis-Plus已经提供了大量的自定义设置,生成的代码完全能够满足各类型的需求,基本覆盖了大部分的配置了。这里贴一个比较完整的代码生成器类,大家可根据实际情况进行修改。

MysqlGenerator.java:

//省略了import
public class MysqlGenerator {

    
    private static final String PACKAGE_NAME = "cn.lqdev.learning.mybatisplus.samples";
    
    private static final String MODULE_NAME = "biz";
    
    private static final String OUT_PATH = "D:\develop\code";
    
    private static final String AUTHOR = "oKong";

    
    private static final String DRIVER = "com.mysql.jdbc.Driver";
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/learning?useUnicode=true&characterEncoding=UTF-8";
    private static final String USER_NAME = "root";
    private static final String PASSWORD = "bs";

    
    public static void main(String[] args) {
 // 自定义需要填充的字段
 List tableFillList = new ArrayList();
 //如 每张表都有一个创建时间、修改时间
 //而且这基本上就是通用的了,新增时,创建时间和修改时间同时修改
 //修改时,修改时间会修改,
 //虽然像Mysql数据库有自动更新几只,但像ORACLE的数据库就没有了,
 //使用公共字段填充功能,就可以实现,自动按场景更新了。
 //如下是配置
 TableFill createField = new TableFill("gmt_create", FieldFill.INSERT); 
 TableFill modifiedField = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE); 
 tableFillList.add(createField);
 tableFillList.add(modifiedField);
 
 // 代码生成器
 AutoGenerator mpg = new AutoGenerator().setGlobalConfig(
  // 全局配置
  new GlobalConfig().setOutputDir(OUT_PATH)// 输出目录
   .setFileOverride(true)// 是否覆盖文件
   .setActiveRecord(true)// 开启 activeRecord 模式
   .setEnableCache(false)// XML 二级缓存
   .setbaseResultMap(false)// XML ResultMap
   .setbaseColumnList(true)// XML columList
   .setAuthor(AUTHOR)
   // 自定义文件命名,注意 %s 会自动填充表实体属性!
   .setXmlName("%sMapper").setMapperName("%sDao")
 // .setServiceName("MP%sService")
 // .setServiceImplName("%sServiceDiy")
 // .setControllerName("%sAction")
 ).setDataSource(
  // 数据源配置
  new DataSourceConfig().setDbType(DbType.MYSQL)// 数据库类型
   .setTypeConvert(new MySqlTypeConvert() {
// 自定义数据库表字段类型转换【可选】
@Override
public DbColumnType processTypeConvert(String fieldType) {
    System.out.println("转换类型:" + fieldType);
    // if ( fieldType.toLowerCase().contains( "tinyint" ) ) {
    // return DbColumnType.BOOLEAN;
    // }
    return super.processTypeConvert(fieldType);
}
   }).setDriverName(DRIVER).setUsername(USER_NAME).setPassword(PASSWORD).setUrl(URL))
  .setStrategy(
   // 策略配置
   new StrategyConfig()
    // .setCapitalMode(true)// 全局大写命名
    .setDbColumnUnderline(true)// 全局下划线命名
    // .setTablePrefix(new String[]{"unionpay_"})// 此处可以修改为您的表前缀
    .setNaming(NamingStrategy.underline_to_camel)// 表名生成策略
    // .setInclude(new String[] {"user"}) // 需要生成的表
    // .setExclude(new String[]{"test"}) // 排除生成的表
    // 自定义实体,公共字段
    // .setSuperEntityColumns(new String[]{"test_id"})
    .setTableFillList(tableFillList)
    // 自定义实体父类
    // .setSuperEntityClass("com.baomidou.demo.base.BsbaseEntity")
    // // 自定义 mapper 父类
    // .setSuperMapperClass("com.baomidou.demo.base.BsbaseMapper")
    // // 自定义 service 父类
    // .setSuperServiceClass("com.baomidou.demo.base.BsbaseService")
    // // 自定义 service 实现类父类
    // .setSuperServiceImplClass("com.baomidou.demo.base.BsbaseServiceImpl")
    // 自定义 controller 父类
    // .setSuperControllerClass("com.baomidou.demo.TestController")
    // 【实体】是否生成字段常量(默认 false)
    // public static final String ID = "test_id";
    .setEntityColumnConstant(true)
    // 【实体】是否为构建者模型(默认 false)
    // public User setName(String name) {this.name = name; return this;}
    .setEntityBuilderModel(true)
    // 【实体】是否为lombok模型(默认 false)document
    .setEntityLombokModel(true)
  // Boolean类型字段是否移除is前缀处理
  // .setEntityBooleanColumnRemoveIsPrefix(true)
  // .setRestControllerStyle(true)
  // .setControllerMappingHyphenStyle(true)
  ).setPackageInfo(
   // 包配置
   new PackageConfig().setModuleName(MODULE_NAME).setParent(PACKAGE_NAME)// 自定义包路径
    .setController("controller")// 这里是控制器包名,默认 web
    .setXml("mapper").setMapper("dao")

  ).setCfg(
   // 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值
   new InjectionConfig() {
@Override
public void initMap() {
    Map map = new HashMap();
    map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
    this.setMap(map);
}
   }.setFileOutConfigList(
    Collections.singletonList(new FileOutConfig("/templates/mapper.xml.vm") {
 // 自定义输出文件目录
 @Override
 public String outputFile(TableInfo tableInfo) {
     return OUT_PATH + "/xml/" + tableInfo.getEntityName() + "Mapper.xml";
 }
    })))
  .setTemplate(
   // 关闭默认 xml 生成,调整生成 至 根目录
   new TemplateConfig().setXml(null)
 // 自定义模板配置,模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy
 // 至您项目 src/main/resources/template 目录下,模板名称也可自定义如下配置:
 // .setController("...");
 // .setEntity("...");
 // .setMapper("...");
 // .setXml("...");
 // .setService("...");
 // .setServiceImpl("...");
 );

 // 执行生成
 mpg.execute();
    }

}

按以上代码生成器,生成的目录结构如下(依赖中需要加入velocity-engine-core包,是利用模版引擎来生成的)

对应mapper.xml

对于需要自定义模版时,大家可查看官方的mybatis-plus-generate包,默认的官方模版都放在此包下。

有了代码生成器,省了很多机械性的复制黏贴操作,还不会出错,写错了再执行一次就好了!

通用的CURD

MP提供了ActiveRecord的支持,所以实体类只需继承 Model 类即可实现基本 CRUD 操作。

这里以编写测试类的形式,进行通用CURD操作,代码类有相应的注释说明。

GeneralTest.java:


@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest 
@Slf4j
public class GeneralTest {

    @Autowired
    IUserService userService;
    
    @Test
    public void testInsert() {
 User user = new User();
 user.setCode("001");
 user.setName("okong-insert");
 //默认的插入策略为:FieldStrategy.NOT_NULL,即:判断 null
 //对应在mapper.xml时写法为:
 //这个可以修改的,设置字段的@TableField(strategy=FieldStrategy.NOT_EMPTY)
 //所以这个时候,为null的字段是不会更新的,也可以开启性能插件,查看sql语句就可以知道
 userService.insert(user);
 
 //新增所有字段,
 userService.insertAllColumn(user);
 log.info("新增结束");
    }
    
    @Test
    public void testUpdate() {
 
 User user = new User();
 user.setCode("101");
 user.setName("oKong-insert");
 //这就是ActiveRecord的功能
 user.insert();
 //也可以直接 userService.insert(user);

 //更新
 User updUser = new User();
 updUser.setId(user.getId());
 updUser.setName("okong-upd");
 
 updUser.updateById();
 log.info("更新结束");
    }
    
    @Test
    public void testDelete() {
 User user = new User();
 user.setCode("101");
 user.setName("oKong-delete");
 
 user.insert();
 
 //删除
 user.deleteById();
 log.info("删除结束");

    }
    
    @Test
    public void testSelect() {
 User user = new User();
 user.setCode("201");
 user.setName("oKong-selecdt");
 
 user.insert();
 
 log.info("查询:{}",user.selectById());
    }
}

以上就列举了常用的,官方提供了很多的通用方法:

注意控制台的sql输出,对比下就知道各方法之间的区别了。


对于通用代码如何注入的,可查看com.baomidou.mybatisplus.mapper.AutoSqlInjector类,这个就是注入通用的CURD方法的类。


条件构造器

在通用的CURD无法满足时,这个时候 强大的条件构造器就排上用场了。主要提供了实体包装器,用于处理 sql 拼接,排序,实体参数查询等!

这里需要注意:使用的是数据库字段,不是Java属性!,原来使用另一款通用mapper时记得使用的是JAVA属性。

sql条件拼接

这也是条件构造器最灵活的地方了。

ConditionTest.java

@RunWith(SpringRunner.class)
//SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest 
@Slf4j
public class ConditionTest {
	
	@Autowired
	IUserService userService;
	
	@Test
	public void testOne() {
		User user =  new User();
		user.setCode("701");
		user.setName("okong-condition");
	    user.insert();
	    
		EntityWrapper qryWrapper = new EntityWrapper<>();
		
		qryWrapper.eq(User.CODE, user.getCode());
		qryWrapper.eq(User.NAME, user.getName());
		
		//也可以直接 
//		qryWrapper.setEntity(user);
		
		//打印sql语句
		System.out.println(qryWrapper.getSqlSegment());
		
		//设置select 字段 即:select code,name from 
		qryWrapper.setSqlSelect(User.CODE,User.NAME);
		System.out.println(qryWrapper.getSqlSelect());
		
		//查询
	    User qryUser = userService.selectOne(qryWrapper);
	    System.out.println(qryUser);
	    log.info("拼接一结束");
	}
	
	@Test
	public void testTwo() {
		User user =  new User();
		user.setCode("702");
		user.setName("okong-condition");
	    user.insert();
	    
		EntityWrapper qryWrapper = new EntityWrapper<>();
		qryWrapper.where("code = {0}", user.getCode())
		.and("name = {0}",user.getName())
		.andNew("status = 0");
		System.out.println(qryWrapper.getSqlSegment());
		//等等很复杂的。
		//复杂的建议直接写在xml里面了,要是非动态的话 比较xml一眼看得懂呀
		//查询
	    User qryUser = userService.selectOne(qryWrapper);
	    System.out.println(qryUser);
	    log.info("拼接二结束");
	}

}

com.baomidou.mybatisplus.mapper.Wrapper类还有很多的方法,大家可以试试。

条件参数说明

查询方式 说明
setSqlSelect 设置 SELECT 查询字段
where WHERe 语句,拼接 + WHERe 条件
and AND 语句,拼接 + AND 字段=值
andNew AND 语句,拼接 + AND (字段=值)
or OR 语句,拼接 + OR 字段=值
orNew OR 语句,拼接 + OR (字段=值)
eq 等于=
allEq 基于 map 内容等于=
ne 不等于<>
gt 大于>
ge 大于等于>=
lt 小于<
le 小于等于<=
like 模糊查询 LIKE
notLike 模糊查询 NOT LIKE
in IN 查询
notIn NOT IN 查询
isNull NULL 值查询
isNotNull IS NOT NULL
groupBy 分组 GROUP BY
having HAVINg 关键词
orderBy 排序 ORDER BY
orderAsc ASC 排序 ORDER BY
orderDesc DESC 排序 ORDER BY
exists EXISTS 条件语句
notExists NOT EXISTS 条件语句
between BETWEEN 条件语句
notBetween NOT BETWEEN 条件语句
addFilter 自由拼接 SQL
last 拼接在最后,例如:last(“LIMIT 1”)

自定义SQL使用条件构造器

UserDao.java加入接口方法:


	List selectUserWrapper(RowBounds rowBounds, @Param("ew") Wrapper wrapper);

UserMapper.xml加入对应的xml节点:

    
	
		SELECT
		
		FROM USER
		
			${ew.sqlSegment}
		
	

自定义SQL语句

在一些需要多表关联时,条件构造器和通用CURD都无法满足时,还可以自行手写sql语句进行扩展。注意:这都是mybatis的用法。

以下两种方式都是改造UserDao接口。

注解形式
@Select("SELECT * FROM USER WHERe CODE = #{userCode}")
	List selectUserCustomParamsByAnno(@Param("userCode")String userCode);

xml形式
List selectUserCustomParamsByXml(@Param("userCode")String userCode);

同时,UserMapper.xml新增一个节点: