SpringBoot整合MyBatis-Plus3.1教程详解
一.说明
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过度的那种感觉
嗯,这玩意真香~