Mybatis-Plus使用全解
前言
之前写了《SpringBoot | 第九章:Mybatis-plus 的集成和使用》一文,只是简单的使用条件构造器列举了一些通用的 CURD 操作。本人也想写一篇通用的关于
mybatis-plus
的使用示例,一方面也让自己更加了解mybatis
和mybatis-plus
,另一方面,也因为很多新人刚入职公司时,对这块不是很熟悉,会有一些疑惑。所以,总的来说还是作为一份资产,可供人查阅,这样也能减少了很多的沟通成本。
所以本章节,就主要来讲解下关于Mybatis-plus
的不同场景的用法,目前主要想到的是以下几个知识点,也是很常用的知识点了,后面有补充的会再启章节来记录的。另外,官网的文档已经很详尽了,大家可认真查阅下。
- 代码生成器
- 通用的 CURD
- 条件构造器
- 自定义 SQL 语句
- 分页插件、性能分析插件
- 公共字段自动填充
工程准备
这里还是以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 {
<span class="hljs-comment">/**
* 包名
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">PACKAGE_NAME</span> <span class="hljs-operator">=</span> <span class="hljs-string">"cn.lqdev.learning.mybatisplus.samples"</span>;
<span class="hljs-comment">/**
* 模块名称
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">MODULE_NAME</span> <span class="hljs-operator">=</span> <span class="hljs-string">"biz"</span>;
<span class="hljs-comment">/**
* 输出文件的路径
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">OUT_PATH</span> <span class="hljs-operator">=</span> <span class="hljs-string">"D:\\develop\\code"</span>;
<span class="hljs-comment">/**
* 代码生成者
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">AUTHOR</span> <span class="hljs-operator">=</span> <span class="hljs-string">"oKong"</span>;
<span class="hljs-comment">/**
* JDBC相关配置
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">DRIVER</span> <span class="hljs-operator">=</span> <span class="hljs-string">"com.mysql.jdbc.Driver"</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">URL</span> <span class="hljs-operator">=</span> <span class="hljs-string">"jdbc:mysql://127.0.0.1:3306/learning?useUnicode=true&characterEncoding=UTF-8"</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">USER_NAME</span> <span class="hljs-operator">=</span> <span class="hljs-string">"root"</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">PASSWORD</span> <span class="hljs-operator">=</span> <span class="hljs-string">"bs"</span>;
<span class="hljs-comment">/**
* <p>
* MySQL 生成演示
* </p>
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> {
<span class="hljs-comment">// 自定义需要填充的字段</span>
List<TableFill> tableFillList = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><TableFill>();
<span class="hljs-comment">//如 每张表都有一个创建时间、修改时间</span>
<span class="hljs-comment">//而且这基本上就是通用的了,新增时,创建时间和修改时间同时修改</span>
<span class="hljs-comment">//修改时,修改时间会修改,</span>
<span class="hljs-comment">//虽然像Mysql数据库有自动更新几只,但像ORACLE的数据库就没有了,</span>
<span class="hljs-comment">//使用公共字段填充功能,就可以实现,自动按场景更新了。</span>
<span class="hljs-comment">//如下是配置</span>
<span class="hljs-type">TableFill</span> <span class="hljs-variable">createField</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">TableFill</span>(<span class="hljs-string">"gmt_create"</span>, FieldFill.INSERT);
<span class="hljs-type">TableFill</span> <span class="hljs-variable">modifiedField</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">TableFill</span>(<span class="hljs-string">"gmt_modified"</span>, FieldFill.INSERT_UPDATE);
tableFillList.add(createField);
tableFillList.add(modifiedField);
<span class="hljs-comment">// 代码生成器</span>
<span class="hljs-type">AutoGenerator</span> <span class="hljs-variable">mpg</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">AutoGenerator</span>().setGlobalConfig(
<span class="hljs-comment">// 全局配置</span>
<span class="hljs-keyword">new</span> <span class="hljs-title class_">GlobalConfig</span>().setOutputDir(OUT_PATH)<span class="hljs-comment">// 输出目录</span>
.setFileOverride(<span class="hljs-literal">true</span>)<span class="hljs-comment">// 是否覆盖文件</span>
.setActiveRecord(<span class="hljs-literal">true</span>)<span class="hljs-comment">// 开启 activeRecord 模式</span>
.setEnableCache(<span class="hljs-literal">false</span>)<span class="hljs-comment">// XML 二级缓存</span>
.setBaseResultMap(<span class="hljs-literal">false</span>)<span class="hljs-comment">// XML ResultMap</span>
.setBaseColumnList(<span class="hljs-literal">true</span>)<span class="hljs-comment">// XML columList</span>
.setAuthor(AUTHOR)
<span class="hljs-comment">// 自定义文件命名,注意 %s 会自动填充表实体属性!</span>
.setXmlName(<span class="hljs-string">"%sMapper"</span>).setMapperName(<span class="hljs-string">"%sDao"</span>)
<span class="hljs-comment">// .setServiceName("MP%sService")</span>
<span class="hljs-comment">// .setServiceImplName("%sServiceDiy")</span>
<span class="hljs-comment">// .setControllerName("%sAction")</span>
).setDataSource(
<span class="hljs-comment">// 数据源配置</span>
<span class="hljs-keyword">new</span> <span class="hljs-title class_">DataSourceConfig</span>().setDbType(DbType.MYSQL)<span class="hljs-comment">// 数据库类型</span>
.setTypeConvert(<span class="hljs-keyword">new</span> <span class="hljs-title class_">MySqlTypeConvert</span>() {
<span class="hljs-comment">// 自定义数据库表字段类型转换【可选】</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> DbColumnType <span class="hljs-title function_">processTypeConvert</span><span class="hljs-params">(String fieldType)</span> {
System.out.println(<span class="hljs-string">"转换类型:"</span> + fieldType);
<span class="hljs-comment">// if ( fieldType.toLowerCase().contains( "tinyint" ) ) {</span>
<span class="hljs-comment">// return DbColumnType.BOOLEAN;</span>
<span class="hljs-comment">// }</span>
<span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.processTypeConvert(fieldType);
}
}).setDriverName(DRIVER).setUsername(USER_NAME).setPassword(PASSWORD).setUrl(URL))
.setStrategy(
<span class="hljs-comment">// 策略配置</span>
<span class="hljs-keyword">new</span> <span class="hljs-title class_">StrategyConfig</span>()
<span class="hljs-comment">// .setCapitalMode(true)// 全局大写命名</span>
.setDbColumnUnderline(<span class="hljs-literal">true</span>)<span class="hljs-comment">// 全局下划线命名</span>
<span class="hljs-comment">// .setTablePrefix(new String[]{"unionpay_"})// 此处可以修改为您的表前缀</span>
.setNaming(NamingStrategy.underline_to_camel)<span class="hljs-comment">// 表名生成策略</span>
<span class="hljs-comment">// .setInclude(new String[] {"user"}) // 需要生成的表</span>
<span class="hljs-comment">// .setExclude(new String[]{"test"}) // 排除生成的表</span>
<span class="hljs-comment">// 自定义实体,公共字段</span>
<span class="hljs-comment">// .setSuperEntityColumns(new String[]{"test_id"})</span>
.setTableFillList(tableFillList)
<span class="hljs-comment">// 自定义实体父类</span>
<span class="hljs-comment">// .setSuperEntityClass("com.baomidou.demo.base.BsBaseEntity")</span>
<span class="hljs-comment">// // 自定义 mapper 父类</span>
<span class="hljs-comment">// .setSuperMapperClass("com.baomidou.demo.base.BsBaseMapper")</span>
<span class="hljs-comment">// // 自定义 service 父类</span>
<span class="hljs-comment">// .setSuperServiceClass("com.baomidou.demo.base.BsBaseService")</span>
<span class="hljs-comment">// // 自定义 service 实现类父类</span>
<span class="hljs-comment">// .setSuperServiceImplClass("com.baomidou.demo.base.BsBaseServiceImpl")</span>
<span class="hljs-comment">// 自定义 controller 父类</span>
<span class="hljs-comment">// .setSuperControllerClass("com.baomidou.demo.TestController")</span>
<span class="hljs-comment">// 【实体】是否生成字段常量(默认 false)</span>
<span class="hljs-comment">// public static final String ID = "test_id";</span>
.setEntityColumnConstant(<span class="hljs-literal">true</span>)
<span class="hljs-comment">// 【实体】是否为构建者模型(默认 false)</span>
<span class="hljs-comment">// public User setName(String name) {this.name = name; return this;}</span>
.setEntityBuilderModel(<span class="hljs-literal">true</span>)
<span class="hljs-comment">// 【实体】是否为lombok模型(默认 false)<a href="https://projectlombok.org/">document</a></span>
.setEntityLombokModel(<span class="hljs-literal">true</span>)
<span class="hljs-comment">// Boolean类型字段是否移除is前缀处理</span>
<span class="hljs-comment">// .setEntityBooleanColumnRemoveIsPrefix(true)</span>
<span class="hljs-comment">// .setRestControllerStyle(true)</span>
<span class="hljs-comment">// .setControllerMappingHyphenStyle(true)</span>
).setPackageInfo(
<span class="hljs-comment">// 包配置</span>
<span class="hljs-keyword">new</span> <span class="hljs-title class_">PackageConfig</span>().setModuleName(MODULE_NAME).setParent(PACKAGE_NAME)<span class="hljs-comment">// 自定义包路径</span>
.setController(<span class="hljs-string">"controller"</span>)<span class="hljs-comment">// 这里是控制器包名,默认 web</span>
.setXml(<span class="hljs-string">"mapper"</span>).setMapper(<span class="hljs-string">"dao"</span>)
).setCfg(
<span class="hljs-comment">// 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值</span>
<span class="hljs-keyword">new</span> <span class="hljs-title class_">InjectionConfig</span>() {
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">initMap</span><span class="hljs-params">()</span> {
Map<String, Object> map = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><String, Object>();
map.put(<span class="hljs-string">"abc"</span>, <span class="hljs-built_in">this</span>.getConfig().getGlobalConfig().getAuthor() + <span class="hljs-string">"-mp"</span>);
<span class="hljs-built_in">this</span>.setMap(map);
}
}.setFileOutConfigList(
Collections.<FileOutConfig>singletonList(<span class="hljs-keyword">new</span> <span class="hljs-title class_">FileOutConfig</span>(<span class="hljs-string">"/templates/mapper.xml.vm"</span>) {
<span class="hljs-comment">// 自定义输出文件目录</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> String <span class="hljs-title function_">outputFile</span><span class="hljs-params">(TableInfo tableInfo)</span> {
<span class="hljs-keyword">return</span> OUT_PATH + <span class="hljs-string">"/xml/"</span> + tableInfo.getEntityName() + <span class="hljs-string">"Mapper.xml"</span>;
}
})))
.setTemplate(
<span class="hljs-comment">// 关闭默认 xml 生成,调整生成 至 根目录</span>
<span class="hljs-keyword">new</span> <span class="hljs-title class_">TemplateConfig</span>().setXml(<span class="hljs-literal">null</span>)
<span class="hljs-comment">// 自定义模板配置,模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy</span>
<span class="hljs-comment">// 至您项目 src/main/resources/template 目录下,模板名称也可自定义如下配置:</span>
<span class="hljs-comment">// .setController("...");</span>
<span class="hljs-comment">// .setEntity("...");</span>
<span class="hljs-comment">// .setMapper("...");</span>
<span class="hljs-comment">// .setXml("...");</span>
<span class="hljs-comment">// .setService("...");</span>
<span class="hljs-comment">// .setServiceImpl("...");</span>
);
<span class="hljs-comment">// 执行生成</span>
mpg.execute();
}
}
按以上代码生成器,生成的目录结构如下(依赖中需要加入velocity-engine-core
包,是利用模版引擎来生成的)
对应 mapper.xml
对于需要自定义模版时,大家可查看官方的mybatis-plus-generate
包,默认的官方模版都放在此包下。
有了代码生成器,省了很多机械性的复制黏贴操作,还不会出错,写错了再执行一次就好了!
通用的 CURD
MP
提供了ActiveRecord
的支持,所以实体类只需继承 Model 类即可实现基本 CRUD 操作。
这里以编写测试类的形式,进行通用 CURD 操作,代码类有相应的注释说明。
GeneralTest.java:
/**
* 通用 CURD 示例
* @author oKong
*
*/
@RunWith(SpringRunner.class)
//SpringBootTest 是 springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest
@Slf4j
public class GeneralTest {
<span class="hljs-meta">@Autowired</span>
IUserService userService;
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testInsert</span><span class="hljs-params">()</span> {
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"001"</span>);
user.setName(<span class="hljs-string">"okong-insert"</span>);
<span class="hljs-comment">//默认的插入策略为:FieldStrategy.NOT_NULL,即:判断 null</span>
<span class="hljs-comment">//对应在mapper.xml时写法为:<if test="field!=null"></span>
<span class="hljs-comment">//这个可以修改的,设置字段的@TableField(strategy=FieldStrategy.NOT_EMPTY)</span>
<span class="hljs-comment">//所以这个时候,为null的字段是不会更新的,也可以开启性能插件,查看sql语句就可以知道</span>
userService.insert(user);
<span class="hljs-comment">//新增所有字段,</span>
userService.insertAllColumn(user);
log.info(<span class="hljs-string">"新增结束"</span>);
}
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testUpdate</span><span class="hljs-params">()</span> {
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"101"</span>);
user.setName(<span class="hljs-string">"oKong-insert"</span>);
<span class="hljs-comment">//这就是ActiveRecord的功能</span>
user.insert();
<span class="hljs-comment">//也可以直接 userService.insert(user);</span>
<span class="hljs-comment">//更新</span>
<span class="hljs-type">User</span> <span class="hljs-variable">updUser</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
updUser.setId(user.getId());
updUser.setName(<span class="hljs-string">"okong-upd"</span>);
updUser.updateById();
log.info(<span class="hljs-string">"更新结束"</span>);
}
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testDelete</span><span class="hljs-params">()</span> {
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"101"</span>);
user.setName(<span class="hljs-string">"oKong-delete"</span>);
user.insert();
<span class="hljs-comment">//删除</span>
user.deleteById();
log.info(<span class="hljs-string">"删除结束"</span>);
}
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testSelect</span><span class="hljs-params">()</span> {
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"201"</span>);
user.setName(<span class="hljs-string">"oKong-selecdt"</span>);
user.insert();
log.info(<span class="hljs-string">"查询:{}"</span>,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 {
<span class="hljs-meta">@Autowired</span>
IUserService userService;
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testOne</span><span class="hljs-params">()</span> {
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"701"</span>);
user.setName(<span class="hljs-string">"okong-condition"</span>);
user.insert();
EntityWrapper<User> qryWrapper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">EntityWrapper</span><>();
qryWrapper.eq(User.CODE, user.getCode());
qryWrapper.eq(User.NAME, user.getName());
<span class="hljs-comment">//也可以直接 </span>
// qryWrapper.setEntity(user);
<span class="hljs-comment">//打印sql语句</span>
System.out.println(qryWrapper.getSqlSegment());
<span class="hljs-comment">//设置select 字段 即:select code,name from </span>
qryWrapper.setSqlSelect(User.CODE,User.NAME);
System.out.println(qryWrapper.getSqlSelect());
<span class="hljs-comment">//查询</span>
<span class="hljs-type">User</span> <span class="hljs-variable">qryUser</span> <span class="hljs-operator">=</span> userService.selectOne(qryWrapper);
System.out.println(qryUser);
log.info(<span class="hljs-string">"拼接一结束"</span>);
}
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testTwo</span><span class="hljs-params">()</span> {
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"702"</span>);
user.setName(<span class="hljs-string">"okong-condition"</span>);
user.insert();
EntityWrapper<User> qryWrapper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">EntityWrapper</span><>();
qryWrapper.where(<span class="hljs-string">"code = {0}"</span>, user.getCode())
.and(<span class="hljs-string">"name = {0}"</span>,user.getName())
.andNew(<span class="hljs-string">"status = 0"</span>);
System.out.println(qryWrapper.getSqlSegment());
<span class="hljs-comment">//等等很复杂的。</span>
<span class="hljs-comment">//复杂的建议直接写在xml里面了,要是非动态的话 比较xml一眼看得懂呀</span>
<span class="hljs-comment">//查询</span>
<span class="hljs-type">User</span> <span class="hljs-variable">qryUser</span> <span class="hljs-operator">=</span> userService.selectOne(qryWrapper);
System.out.println(qryUser);
log.info(<span class="hljs-string">"拼接二结束"</span>);
}
}
com.baomidou.mybatisplus.mapper.Wrapper<T>
类还有很多的方法,大家可以试试。
条件参数说明
查询方式 | 说明 |
---|---|
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
加入接口方法:
/**
*
* @param rowBounds 分页对象 直接传入 page 即可
* @param wrapper 条件构造器
* @return
*/
List<User> selectUserWrapper(RowBounds rowBounds, @Param("ew") Wrapper<User> wrapper);
UserMapper.xml
加入对应的 xml 节点:
<!-- 条件构造器形式 -->
<select id="selectUserWrapper" resultType="user">
SELECT
<include refid="Base_Column_List" />
FROM USER
<where>
${ew.sqlSegment}
</where>
</select>
测试类:
@Test
public void testCustomSql() {
User user = new User();
user.setCode("703");
user.setName("okong-condition");
user.insert();
EntityWrapper<User> qryWrapper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">EntityWrapper</span><>();
qryWrapper.eq(User.CODE, user.getCode());
Page<User> pageUser = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Page</span><>();
pageUser.setCurrent(<span class="hljs-number">1</span>);
pageUser.setSize(<span class="hljs-number">10</span>);
List<User> userlist = userDao.selectUserWrapper(pageUser, qryWrapper);
System.out.println(userlist.get(<span class="hljs-number">0</span>));
log.info(<span class="hljs-string">"自定义sql结束"</span>);
}
xml 形式使用 wrapper
UserDao.java
/**
*
* @param rowBounds 分页对象 直接传入 page 即可
* @param wrapper 条件构造器
* @return
*/
List<User> selectUserWrapper(RowBounds rowBounds, @Param("ew") Wrapper<User> wrapper);
对应的UserMapper.xml
:
<!-- 条件构造器形式 -->
<select id="selectUserWrapper" resultType="user">
SELECT
<include refid="Base_Column_List" />
FROM USER
<where>
${ew.sqlSegment}
</where>
</select>
自定义 SQL 语句
在一些需要多表关联时,条件构造器和通用 CURD 都无法满足时,还可以自行手写 sql 语句进行扩展。注意:这都是
mybatis
的用法。
以下两种方式都是改造UserDao
接口。
注解形式
@Select("SELECT * FROM USER WHERE CODE = #{userCode}")
List<User> selectUserCustomParamsByAnno(@Param("userCode")String userCode);
xml 形式
List<User> selectUserCustomParamsByXml(@Param("userCode")String userCode);
同时,UserMapper.xml
新增一个节点:
<!-- 由于设置了别名:typeAliasesPackage=cn.lqdev.learning.mybatisplus.samples.biz.entity,所以 resultType 可以不写全路径了。 -->
<select id="selectUserCustomParamsByXml" resultType="user">
SELECT
<include refid="Base_Column_List"/>
FROM USER
WHERE CODE = #{userCode}
</select>
测试类CustomSqlTest.java
:
@RunWith(SpringRunner.class)
//SpringBootTest 是 springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest
@Slf4j
public class CustomSqlTest {
<span class="hljs-meta">@Autowired</span>
UserDao userDao;
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testCustomAnno</span><span class="hljs-params">()</span> {
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"901"</span>);
user.setName(<span class="hljs-string">"okong-sql"</span>);
user.insert();
List<User> userlist = userDao.selectUserCustomParamsByAnno(user.getCode());
<span class="hljs-comment">//由于新增的 肯定不为null 故不判断了。</span>
System.out.println(userlist.get(<span class="hljs-number">0</span>).toString());
log.info(<span class="hljs-string">"注解形式结束------"</span>);
}
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testCustomXml</span><span class="hljs-params">()</span> {
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"902"</span>);
user.setName(<span class="hljs-string">"okong-sql"</span>);
user.insert();
List<User> userlist = userDao.selectUserCustomParamsByXml(user.getCode());
<span class="hljs-comment">//由于新增的 肯定不为null 故不判断了。</span>
System.out.println(userlist.get(<span class="hljs-number">0</span>).toString());
log.info(<span class="hljs-string">"xml形式结束------"</span>);
}
}
注意事项
在使用spring-boot-maven-plugin
插件打包成springboot
运行 jar 时,需要注意下,由于springboot
的 jar 扫描路径方式问题,会导致别名的包未扫描到,所以这个只需要把mybatis
默认的扫描设置为Springboot
的VFS
实现。
直接修改spring-mybatis.xml
文件:
<!--mybatis-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 自动扫描 mapper.xml 文件,支持通配符 -->
<property name="mapperLocations" value="classpath:mapper/**/*.xml"/>
<!-- 配置文件,比如参数配置 (是否启动驼峰等)、插件配置等 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<!-- 启用别名,这样就无需写全路径类名了,具体可自行查阅资料 -->
<property name="typeAliasesPackage" value="cn.lqdev.learning.mybatisplus.samples.biz.entity"/>
<!-- MP 全局配置注入 -->
<property name="globalConfig" ref="globalConfig"/>
<!-- 设置 vfs 实现,避免路径扫描问题 -->
<property name="vfs" value="com.baomidou.mybatisplus.spring.boot.starter.SpringBootVFS"></property>
</bean>
分页插件、性能分析插件
mybatis 的插件机制使用起来是很简单的,只需要注册即可。
mybatis-config.xml
<plugins>
<!-- SQL 执行性能分析,开发环境使用,线上不推荐。 -->
<plugin interceptor="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"></plugin>
<!-- 分页插件配置 -->
<plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></plugin>
</plugins>
分页测试类 (性能分析,配置后可以输出 sql 及取数时间):
@RunWith(SpringRunner.class)
//SpringBootTest 是 springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。
@SpringBootTest
@Slf4j
public class PluginTest {
<span class="hljs-meta">@Autowired</span>
IUserService userService;
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testPagination</span><span class="hljs-params">()</span> {
Page<User> page = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Page</span><>();
<span class="hljs-comment">//每页数</span>
page.setSize(<span class="hljs-number">10</span>);
<span class="hljs-comment">//当前页码</span>
page.setCurrent(<span class="hljs-number">1</span>);
<span class="hljs-comment">//无条件时</span>
Page<User> pageList = userService.selectPage(page);
System.out.println(pageList.getRecords().get(<span class="hljs-number">0</span>));
<span class="hljs-comment">//新增数据 避免查询不到数据</span>
<span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();
user.setCode(<span class="hljs-string">"801"</span>);
user.setName(<span class="hljs-string">"okong-Pagination"</span>);
user.insert();
<span class="hljs-comment">//加入条件构造器</span>
EntityWrapper<User> qryWapper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">EntityWrapper</span><>();
<span class="hljs-comment">//这里也能直接设置 entity 这是条件就是entity的非空字段值了</span>
// qryWapper.setEntity(user);
// 这里建议直接用 常量
// qryWapper.eq(User.CODE, user.getCode());
pageList = userService.selectPage(page, qryWapper);
System.out.println(pageList.getRecords().get(0));
log.info("分页结束");
}
}
性能插件体现,控制台输出:
Time:4 ms - ID:cn.lqdev.learning.mybatisplus.samples.biz.dao.UserDao.selectPage
Execute SQL: SELECT id AS id,code,`name`,`status`,gmt_create AS gmtCreate,gmt_modified AS gmtModified FROM user WHERE id=1026120705692434433 AND code='801' AND `name`='okong-Pagination' LIMIT 0,10
公共字段自动填充
通常,每个公司都有自己的表定义,在《阿里巴巴 _Java_ 开发手册》中,就强制规定表必备三字段:id, gmt_create, gmt_modified。所以通常我们都会写个公共的拦截器去实现自动填充比如创建时间和更新时间的,无需开发人员手动设置。而在
MP
中就提供了这么一个公共字段自动填充功能
。
设置填充字段的填充类型
User.java
/**
* 创建时间
*/
@TableField(fill=FieldFill.INSERT)
private Date gmtCreate;
/**
* 修改时间
*/
@TableField(fill=FieldFill.INSERT_UPDATE)
private Date gmtModified;
注意这里是可以在代码生成器
里面配置规则的,可自动配置,详见代码生成器类。
定义处理类
MybatisObjectHandler.java
public class MybatisObjectHandler extends MetaObjectHandler{
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">insertFill</span><span class="hljs-params">(MetaObject metaObject)</span> {
<span class="hljs-comment">//新增时填充的字段</span>
setFieldValByName(<span class="hljs-string">"gmtCreate"</span>, <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>(), metaObject);
setFieldValByName(<span class="hljs-string">"gmtModified"</span>, <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>(), metaObject);
}
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">updateFill</span><span class="hljs-params">(MetaObject metaObject)</span> {
<span class="hljs-comment">//更新时 需要填充字段</span>
setFieldValByName(<span class="hljs-string">"gmtModified"</span>, <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>(), metaObject);
}
}
同时修改springb-mybatis.xml
文件,加入此配置:
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!--
AUTO->`0`("数据库 ID 自增")QW
INPUT->`1`(用户输入 ID")
ID_WORKER->`2`("全局唯一 ID")
UUID->`3`("全局唯一 ID")
-->
<property name="idType" value="2" />
<property name="metaObjectHandler" ref="mybatisObjectHandler"></property>
</bean>
<span class="hljs-tag"><<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"mybatisObjectHandler"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cn.lqdev.learning.mybatisplus.samples.config.MybatisObjectHandler"</span>/></span>
这个时候再新增或者修改,对应时间就会进行更新了。
Time:31 ms - ID:cn.lqdev.learning.mybatisplus.samples.biz.dao.UserDao.insert
Execute SQL: INSERT INTO user ( id, code, `name`, gmt_create,gmt_modified ) VALUES ( 1026135016838037506, '702', 'okong-condition', '2018-08-05 23:57:07.344','2018-08-05 23:57:07.344' )
相关资料
- MP 官网:http://mp.baomidou.com
总结
本文主要列举了开发过程中常用的操作数据库的方法及相关配置。应该可以应付百分之八十以上的需求了吧。之后有时间,会进行补充的,比如自定义插件、大批量数据的写法等。
最后
若文中有错误或者遗漏之处,还望指出,共同进步!
老生常谈
- 个人 QQ:
499452441
- 微信公众号:
lqdevOps
个人博客:http://blog.lqdev.cn
完整示例:https://gitee.com/oKong/mybatis-plus-samples
原文地址:http://blog.lqdev.cn/2018/08/06/%E6%97%A5%E5%B8%B8%E7%A7%AF%E7%B4%AF/mybatis-plus-guide-one/