SpringBoot整合MyBatis-Plus3.1教程详解

2022-10-16,,,,

一.说明

mybatis-plus是一个mybatis框架的增强插件,根据官方描述,mp只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑.并且只需简单配置,即可快速进行 crud 操作,从而节省大量时间.代码生成,分页,性能分析等功能一应俱全,最新已经更新到了3.1.1版本了,3.x系列支持lambda语法,让我在写条件构造的时候少了很多的"魔法值",从代码结构上更简洁了.

二.项目环境

  • mybatis-plus版本: 3.1.0
  • springboot版本:2.1.5
  • jdk版本:1.8

maven依赖如下:

<dependencies>
  <dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-web</artifactid>
  </dependency>
  <dependency>
   <groupid>mysql</groupid>
   <artifactid>mysql-connector-java</artifactid>
   <scope>runtime</scope>
  </dependency>
  <dependency>
   <groupid>org.projectlombok</groupid>
   <artifactid>lombok</artifactid>
   <optional>true</optional>
  </dependency>
  <dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-test</artifactid>
   <scope>test</scope>
  </dependency>
  <!-- mybatisplus 核心库 -->
  <dependency>
   <groupid>com.baomidou</groupid>
   <artifactid>mybatis-plus-boot-starter</artifactid>
   <version>3.1.0</version>
  </dependency>
  <!-- 引入阿里数据库连接池 -->
  <dependency>
   <groupid>com.alibaba</groupid>
   <artifactid>druid</artifactid>
   <version>1.1.6</version>
  </dependency>
</dependencies>

配置如下:

# 配置端口
server:
 port: 8081
spring:
 # 配置数据源
 datasource:
 driver-class-name: com.mysql.cj.jdbc.driver
 url: jdbc:mysql://localhost:3306/mp_student?useunicode=true&characterencoding=utf-8
 username: root
 password: root
 type: com.alibaba.druid.pool.druiddatasource
# mybatis-plus相关配置
mybatis-plus:
 # xml扫描,多个目录用逗号或者分号分隔(告诉 mapper 所对应的 xml 文件位置)
 mapper-locations: classpath:mapper/*.xml
 # 以下配置均有默认值,可以不设置
 global-config:
 db-config:
  #主键类型 auto:"数据库id自增" input:"用户输入id",id_worker:"全局唯一id (数字类型唯一id)", uuid:"全局唯一id uuid";
  id-type: auto
  #字段策略 ignored:"忽略判断" not_null:"非 null 判断") not_empty:"非空判断"
  field-strategy: not_empty
  #数据库类型
  db-type: mysql
 configuration:
 # 是否开启自动驼峰命名规则映射:从数据库列名到java属性驼峰命名的类似映射
 map-underscore-to-camel-case: true
 # 如果查询结果中包含空值的列,则 mybatis 在映射的时候,不会映射这个字段
 call-setters-on-nulls: true
 # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
 log-impl: org.apache.ibatis.logging.stdout.stdoutimpl
表结构:

create table `user_info` (
 `id` bigint(11) not null auto_increment comment 'id',
 `name` varchar(32) default null comment '姓名',
 `age` int(11) default null comment '年龄',
 `skill` varchar(32) default null comment '技能',
 `evaluate` varchar(64) default null comment '评价',
 `fraction` bigint(11) default null comment '分数',
 primary key (`id`)
) engine=innodb auto_increment=16 default charset=utf8mb4 comment='学生信息表';
表数据:

insert into `user_info` values (1, '小明', 20, '画画', '该学生在画画方面有一定天赋', 89);
insert into `user_info` values (2, '小兰', 19, '游戏', '近期该学生由于游戏的原因导致分数降低了', 64);
insert into `user_info` values (3, '张张', 18, '英语', '近期该学生参加英语比赛获得二等奖', 90);
insert into `user_info` values (4, '大黄', 20, '体育', '该学生近期由于参加篮球比赛,导致脚伤', 76);
insert into `user_info` values (5, '大白', 17, '绘画', '该学生参加美术大赛获得三等奖', 77);
insert into `user_info` values (7, '小龙', 18, 'java', '该学生是一个在改bug的码农', 59);
insert into `user_info` values (9, 'sans', 18, '睡觉', 'sans是一个爱睡觉,并且身材较矮骨骼巨大的骷髅小胖子', 60);
insert into `user_info` values (10, 'papyrus', 18, 'java', 'papyrus是一个讲话大声、个性张扬的骷髅,给人自信、有魅力的骷髅小瘦子', 58);
insert into `user_info` values (11, '删除数据1', 3, '画肖像', null, 61);
insert into `user_info` values (12, '删除数据2', 3, null, null, 61);
insert into `user_info` values (13, '删除数据3', 3, null, null, 61);
insert into `user_info` values (14, '删除数据4', 5, '删除', null, 10);
insert into `user_info` values (15, '删除数据5', 6, '删除', null, 10);

三.编写基础类

在启动类上添加扫描dao的注解

@springbootapplication
@mapperscan(basepackages = {"com.mp.demo.dao"}) //扫描dao
public class demoapplication {
 public static void main(string[] args) {
  springapplication.run(demoapplication.class, args);
 }
}

编写config配置类

/**
 * @description mybatisplus配置类
 * @author sans
 * @createtime 2019/5/26 17:20
 */
@configuration
public class mybatisplusconfig {
 /**
  * mybatis-plus sql执行效率插件【生产环境可以关闭】
  */
 @bean
 public performanceinterceptor performanceinterceptor() {
  return new performanceinterceptor();
 }
 /**
  * 分页插件
  */
 @bean
 public paginationinterceptor paginationinterceptor() {
  return new paginationinterceptor();
 }
}

编写entity类

/**
 * @description 学生信息实体类
 * @author sans
 * @createtime 2019/5/26 21:41
 */
@data
@tablename("user_info")//@tablename中的值对应着表名
public class userinfoentity {

 /**
  * 主键
  * @tableid中可以决定主键的类型,不写会采取默认值,默认值可以在yml中配置
  * auto: 数据库id自增
  * input: 用户输入id
  * id_worker: 全局唯一id,long类型的主键
  * id_worker_str: 字符串全局唯一id
  * uuid: 全局唯一id,uuid类型的主键
  * none: 该类型为未设置主键类型
  */
 @tableid(type = idtype.auto)
 private long id;
 /**
  * 姓名
  */
 private string name;
 /**
  * 年龄
  */
 private integer age;
 /**
  * 技能
  */
 private string skill;
 /**
  * 评价
  */
 private string evaluate;
 /**
  * 分数
  */
 private long fraction;
}

编写dao类

/**
 * @description 用户信息dao
 * @author sans
 * @createtime 2019/6/8 16:24
 */
public interface userinfodao extends basemapper<userinfoentity> {
}

编写service类

/**
 * @description 用户业务接口
 * @author sans
 * @createtime 2019/6/8 16:26
 */
public interface userinfoservice extends iservice<userinfoentity> {
}

编写serviceimpl类

/**
 * @description 用户业务实现
 * @author sans
 * @createtime 2019/6/8 16:26
 */
@service
@transactional
public class userinfoserivceimpl extends serviceimpl<userinfodao, userinfoentity> implements userinfoservice {
}

四.mybatis-plus基础演示

这里我们看到,service中我们没有写任何方法,mybatis-plus官方封装了许多基本crud的方法,可以直接使用大量节约时间,mp共通方法详见iservice,serviceimpl,basemapper源码,写入操作在serviceimpl中已有事务绑定,这里我们举一些常用的方法演示.

/**
 * @description userinfocontroller
 * @author sans
 * @createtime 2019/6/8 16:27
 */
@restcontroller
@requestmapping("/userinfo")
public class userinfocontroller {

 @autowired
 private userinfoservice userinfoservice;

 /**
  * 根据id获取用户信息
  * @author sans
  * @createtime 2019/6/8 16:34
  * @param userid 用户id
  * @return userinfoentity 用户实体
  */
 @requestmapping("/getinfo")
 public userinfoentity getinfo(string userid){
  userinfoentity userinfoentity = userinfoservice.getbyid(userid);
  return userinfoentity;
 }
 /**
  * 查询全部信息
  * @author sans
  * @createtime 2019/6/8 16:35
  * @param userid 用户id
  * @return list<userinfoentity> 用户实体集合
  */
 @requestmapping("/getlist")
 public list<userinfoentity> getlist(){
  list<userinfoentity> userinfoentitylist = userinfoservice.list();
  return userinfoentitylist;
 }
 /**
  * 分页查询全部数据
  * @author sans
  * @createtime 2019/6/8 16:37
  * @return ipage<userinfoentity> 分页数据
  */
 @requestmapping("/getinfolistpage")
 public ipage<userinfoentity> getinfolistpage(){
  //需要在config配置类中配置分页插件
  ipage<userinfoentity> page = new page<>();
  page.setcurrent(5); //当前页
  page.setsize(1); //每页条数
  page = userinfoservice.page(page);
  return page;
 }
 /**
  * 根据指定字段查询用户信息集合
  * @author sans
  * @createtime 2019/6/8 16:39
  * @return collection<userinfoentity> 用户实体集合
  */
 @requestmapping("/getlistmap")
 public collection<userinfoentity> getlistmap(){
  map<string,object> map = new hashmap<>();
  //kay是字段名 value是字段值
  map.put("age",20);
  collection<userinfoentity> userinfoentitylist = userinfoservice.listbymap(map);
  return userinfoentitylist;
 }
 /**
  * 新增用户信息
  * @author sans
  * @createtime 2019/6/8 16:40
  */
 @requestmapping("/saveinfo")
 public void saveinfo(){
  userinfoentity userinfoentity = new userinfoentity();
  userinfoentity.setname("小龙");
  userinfoentity.setskill("java");
  userinfoentity.setage(18);
  userinfoentity.setfraction(59l);
  userinfoentity.setevaluate("该学生是一个在改bug的码农");
  userinfoservice.save(userinfoentity);
 }
 /**
  * 批量新增用户信息
  * @author sans
  * @createtime 2019/6/8 16:42
  */
 @requestmapping("/saveinfolist")
 public void saveinfolist(){
  //创建对象
  userinfoentity sans = new userinfoentity();
  sans.setname("sans");
  sans.setskill("睡觉");
  sans.setage(18);
  sans.setfraction(60l);
  sans.setevaluate("sans是一个爱睡觉,并且身材较矮骨骼巨大的骷髅小胖子");
  userinfoentity papyrus = new userinfoentity();
  papyrus.setname("papyrus");
  papyrus.setskill("java");
  papyrus.setage(18);
  papyrus.setfraction(58l);
  papyrus.setevaluate("papyrus是一个讲话大声、个性张扬的骷髅,给人自信、有魅力的骷髅小瘦子");
  //批量保存
  list<userinfoentity> list =new arraylist<>();
  list.add(sans);
  list.add(papyrus);
  userinfoservice.savebatch(list);
 }
 /**
  * 更新用户信息
  * @author sans
  * @createtime 2019/6/8 16:47
  */
 @requestmapping("/updateinfo")
 public void updateinfo(){
  //根据实体中的id去更新,其他字段如果值为null则不会更新该字段,参考yml配置文件
  userinfoentity userinfoentity = new userinfoentity();
  userinfoentity.setid(1l);
  userinfoentity.setage(19);
  userinfoservice.updatebyid(userinfoentity);
 }
 /**
  * 新增或者更新用户信息
  * @author sans
  * @createtime 2019/6/8 16:50
  */
 @requestmapping("/saveorupdateinfo")
 public void saveorupdate(){
  //传入的实体类userinfoentity中id为null就会新增(id自增)
  //实体类id值存在,如果数据库存在id就会更新,如果不存在就会新增
  userinfoentity userinfoentity = new userinfoentity();
  userinfoentity.setid(1l);
  userinfoentity.setage(20);
  userinfoservice.saveorupdate(userinfoentity);
 }
 /**
  * 根据id删除用户信息
  * @author sans
  * @createtime 2019/6/8 16:52
  */
 @requestmapping("/deleteinfo")
 public void deleteinfo(string userid){
  userinfoservice.removebyid(userid);
 }
 /**
  * 根据id批量删除用户信息
  * @author sans
  * @createtime 2019/6/8 16:55
  */
 @requestmapping("/deleteinfolist")
 public void deleteinfolist(){
  list<string> useridlist = new arraylist<>();
  useridlist.add("12");
  useridlist.add("13");
  userinfoservice.removebyids(useridlist);
 }
 /**
  * 根据指定字段删除用户信息
  * @author sans
  * @createtime 2019/6/8 16:57
  */
 @requestmapping("/deleteinfomap")
 public void deleteinfomap(){
  //kay是字段名 value是字段值
  map<string,object> map = new hashmap<>();
  map.put("skill","删除");
  map.put("fraction",10l);
  userinfoservice.removebymap(map);
 }
}

五.mybatis-plus的querywrapper条件构造器

当查询条件复杂的时候,我们可以使用mp的条件构造器,请参考下面的querywrapper条件参数说明

下面我们来举一些常见的示例

/**
 * @description userinfopluscontroller
 * @author sans
 * @createtime 2019/6/9 14:52
 */
@restcontroller
@requestmapping("/userinfoplus")
public class userinfopluscontroller {

 @autowired
 private userinfoservice userinfoservice;

 /**
  * mp扩展演示
  * @author sans
  * @createtime 2019/6/8 16:37
  * @return map<string,object> 返回数据
  */
 @requestmapping("/getinfolistplus")
 public map<string,object> getinfolistpage(){
  //初始化返回类
  map<string,object> result = new hashmap<>();
  //查询年龄等于18岁的学生
  //等价sql: select id,name,age,skill,evaluate,fraction from user_info where age = 18
  querywrapper<userinfoentity> querywrapper1 = new querywrapper<>();
  querywrapper1.lambda().eq(userinfoentity::getage,18);
  list<userinfoentity> userinfoentitylist1 = userinfoservice.list(querywrapper1);
  result.put("studentage18",userinfoentitylist1);
  //查询年龄大于5岁的学生且小于等于18岁的学生
  //等价sql: select id,name,age,skill,evaluate,fraction from user_info where age > 5 and age <= 18
  querywrapper<userinfoentity> querywrapper2 = new querywrapper<>();
  querywrapper2.lambda().gt(userinfoentity::getage,5);
  querywrapper2.lambda().le(userinfoentity::getage,18);
  list<userinfoentity> userinfoentitylist2 = userinfoservice.list(querywrapper2);
  result.put("studentage5",userinfoentitylist2);
  //模糊查询技能字段带有"画"的数据,并按照年龄降序
  //等价sql: select id,name,age,skill,evaluate,fraction from user_info where skill like '%画%' order by age desc
  querywrapper<userinfoentity> querywrapper3 = new querywrapper<>();
  querywrapper3.lambda().like(userinfoentity::getskill,"画");
  querywrapper3.lambda().orderbydesc(userinfoentity::getage);
  list<userinfoentity> userinfoentitylist3 = userinfoservice.list(querywrapper3);
  result.put("studentageskill",userinfoentitylist3);
  //模糊查询名字带有"小"或者年龄大于18的学生
  //等价sql: select id,name,age,skill,evaluate,fraction from user_info where name like '%小%' or age > 18
  querywrapper<userinfoentity> querywrapper4 = new querywrapper<>();
  querywrapper4.lambda().like(userinfoentity::getname,"小");
  querywrapper4.lambda().or().gt(userinfoentity::getage,18);
  list<userinfoentity> userinfoentitylist4 = userinfoservice.list(querywrapper4);
  result.put("studentor",userinfoentitylist4);
  //查询评价不为null的学生,并且分页
  //等价sql: select id,name,age,skill,evaluate,fraction from user_info where evaluate is not null limit 0,5
  ipage<userinfoentity> page = new page<>();
  page.setcurrent(1);
  page.setsize(5);
  querywrapper<userinfoentity> querywrapper5 = new querywrapper<>();
  querywrapper5.lambda().isnotnull(userinfoentity::getevaluate);
  page = userinfoservice.page(page,querywrapper5);
  result.put("studentpage",page);
  return result;
 }
}

六.自定义sql

引入mybatis-plus不会对项目现有的 mybatis 构架产生任何影响,而且mybatis-plus支持所有 mybatis 原生的特性,这也是我喜欢使用它的原因之一,由于某些业务复杂,我们可能要自己去写一些比较复杂的sql语句,我们举一个简单的例子来演示自定义sql.

示例:查询大于设置分数的学生(分数为动态输入,且有分页)

编写mapper.xml文件

<mapper namespace="com.mp.demo.dao.userinfodao">
 <!-- sans 2019/6/9 14:35 -->
 <select id="selectuserinfobygtfraction" resulttype="com.mp.demo.entity.userinfoentity" parametertype="long">
 select * from user_info where fraction > #{fraction}
 </select>
</mapper>

在dao中加入方法

 /**
  * 查询大于该分数的学生
  * @author sans
  * @createtime 2019/6/9 14:28
  * @param page 分页参数
  * @param fraction 分数
  * @return ipage<userinfoentity> 分页数据
  */
 ipage<userinfoentity> selectuserinfobygtfraction(ipage<userinfoentity> page, long fraction);

在service加入方法

 /**
  * 查询大于该分数的学生
  * @author sans
  * @createtime 2019/6/9 14:27
  * @param page 分页参数
  * @param fraction 分数
  * @return ipage<userinfoentity> 分页数据
  */
 ipage<userinfoentity> selectuserinfobygtfraction(ipage<userinfoentity> page,long fraction);

在serviceimpl加入方法

 /**
  * 查询大于该分数的学生
  * @author sans
  * @createtime 2019/6/9 14:27
  * @param page 分页参数
  * @param fraction 分数
  * @return ipage<userinfoentity> 分页数据
  */
 @override
 public ipage<userinfoentity> selectuserinfobygtfraction(ipage<userinfoentity> page, long fraction) {
  return this.basemapper.selectuserinfobygtfraction(page,fraction);
 }

在controller中测试

 /**
  * mp自定义sql
  * @author sans
  * @createtime 2019/6/9 14:37
  * @return ipage<userinfoentity> 分页数据
  */
 @requestmapping("/getinfolistsql")
 public ipage<userinfoentity> getinfolistsql(){
  //查询大于60分以上的学生,并且分页
  ipage<userinfoentity> page = new page<>();
  page.setcurrent(1);
  page.setsize(5);
  page = userinfoservice.selectuserinfobygtfraction(page,60l);
  return page;
 }

七.项目源码

项目源码:

个人确实很喜欢用mybatis-plus,不仅节约时间,代码也简洁干净,它给了我那时候从ssm到springboot过度的那种感觉

嗯,这玩意真香~

《SpringBoot整合MyBatis-Plus3.1教程详解.doc》

下载本文的Word格式文档,以方便收藏与打印。