当前位置:   article > 正文

Mybatis-Plus入门案例、以及为什么不建议使用MP?_mybatisplus为什么不建议用

mybatisplus为什么不建议用

目录

目录

1 Mybatis调用流程

2 Mybatis与MybatisPlus

2.1 MybatisPlus特点

2.2 Mybatis与MybatisPlus区别

区别1:MybatisPlus自动注入基本 CURD

区别2:MybatisPlus只增强不改变

3 Mybatis与MybatisPlus对比

3.1 准备数据表demo_user

 3.2 项目结构

 3.2.1 导入依赖包

3.2.2 创建对象关系映射User类

3.2.3 创建配置文件

3.2.4 创建Mapper层接口文件

3.3 对比测试

3.3.1 创建测试类

3.3.2 MybatisPlus实现原理

为什么不建议你使用Mybatis-plus


1 Mybatis调用流程

  1. Spring容器为接口创建代理对象. Spring容器启动对象立即创建
  2. 根据 @Autowired 注解动态注入Mapper接口的代理对象
  3. 用户通过Mapper接口调用方法.(执行业务操作)
  4. Mybatis根据接口方法动态匹配xml的映射文件

(1.根据Mapper的接口路径匹配xml映射文件中的 com.jt.mapper.UserMapper
(2.根据接口的方法匹配xml映射文件中的sql id 之后执行Sql语句
(3.Mybatis将结果集封装为对象之后返回.     

2 Mybatis与MybatisPlus

2.1 MybatisPlus特点

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

2.2 Mybatis与MybatisPlus区别

区别1:MybatisPlus自动注入基本 CURD

Mybatis是一种操作数据库的框架,提供一种Mapper类,支持让你用java代码进行增删改查的数据库操作,前提是你得先在xml中写好sql语句,但是每当要写一个业务逻辑的时候都要在DAO层写一个方法,再对应一个SQL,即使是简单的条件查询、或者是仅仅改变了一个条件都要在DAO层新增一个方法,还是有点麻烦。而MybatisPlus自动为Mybatis生成简单的增删改查SQL语句的工具,可以省去手写简单SQL语句的时间,只在XML中编写其它需要的SQL语句,所以MP与mybatis配合使用的话可以很好的提高开发效率。

区别2:MybatisPlus只增强不改变

Mybatis-Plus是一个Mybatis的增强工具,它在Mybatis的基础上做了增强,却不做改变。我们在使用Mybatis-Plus之后既可以使用Mybatis-Plus的特有功能,又能够正常使用Mybatis的原生功能。Mybatis-Plus是为简化开发、提高开发效率而生,但它也提供了一些很有意思的插件,比如SQL性能监控、乐观锁、执行分析等。

3 Mybatis与MybatisPlus对比

3.1 准备数据表demo_user

 

 3.2 项目结构

 3.2.1 导入依赖包

向pom.xml中导入相关依赖包

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.5.2</version>
  5. <relativePath/> <!-- lookup parent from repository -->
  6. </parent>
  7. <properties>
  8. <java.version>1.8</java.version>
  9. <!--跳过测试类打包-->
  10. <skipTests>true</skipTests>
  11. </properties>
  12. <!--原则:按需导入-->
  13. <dependencies>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <!--springboot启动项(器),在包的内部springboot已经完成了项目的“整合”
  17. (配置)用户拿来就能用-->
  18. <artifactId>spring-boot-starter-web</artifactId>
  19. </dependency>
  20. <!--数据库驱动-->
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-jdbc</artifactId>
  24. </dependency>
  25. <!--springboot数据库连接-->
  26. <dependency>
  27. <groupId>mysql</groupId>
  28. <artifactId>mysql-connector-java</artifactId>
  29. </dependency>
  30. <dependency>
  31. <groupId>com.baomidou</groupId>
  32. <artifactId>mybatis-plus-boot-starter</artifactId>
  33. <version>3.4.3</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-test</artifactId>
  38. <scope>test</scope>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.springframework.boot</groupId>
  42. <artifactId>spring-boot-devtools</artifactId>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.projectlombok</groupId>
  46. <artifactId>lombok</artifactId>
  47. </dependency>
  48. </dependencies>
  49. <!--springboot项目与Maven整合的一个插件
  50. 可以通过插件 执行项目打包/测试/文档生成等操作
  51. 注意事项:该插件不能省略,如果省略启动时报错
  52. (省略时)项目发布时:java -jar xxxx.jar 报错没有主清单信息!!
  53. -->
  54. <build>
  55. <plugins>
  56. <plugin>
  57. <groupId>org.springframework.boot</groupId>
  58. <artifactId>spring-boot-maven-plugin</artifactId>
  59. </plugin>
  60. </plugins>
  61. </build>

3.2.2 创建对象关系映射User类

注意user类是与demo_user表对应,属性与字段对应。

  1. package com.jt.pojo;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableField;
  4. import com.baomidou.mybatisplus.annotation.TableId;
  5. import com.baomidou.mybatisplus.annotation.TableName;
  6. import lombok.Data;
  7. import lombok.experimental.Accessors;
  8. import java.io.Serializable;
  9. @Data//使用了lombok插件,不用手写set、get、tostring等方法
  10. @Accessors(chain = true)
  11. @TableName("demo_user")
  12. public class User implements Serializable {
  13. //ID代表主键,不是id字段
  14. @TableId(type=IdType.AUTO)//主键自增
  15. //@TableField("name")//如果属性与字段同名(包括驼峰规则)注解可以省略
  16. private Integer id;
  17. private String name;
  18. private Integer age;
  19. private String sex;
  20. }

3.2.3 创建配置文件

创建UserMapper.xml文件,里面包含大量的SQL语句

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.jt.mapper.UserMapper">
  6. <!--查询表中所有数据-->
  7. <select id="getAll" resultType="User">
  8. select * from demo_user
  9. </select>
  10. <!--查询指定id的数据-->
  11. <select id="getById" resultType="User">
  12. select * from demo_user where id = #{id}
  13. </select>
  14. <!--查询指定sex和age的数据-->
  15. <select id="getByAgeSex" resultType="User">
  16. select * from demo_user where sex = #{sex} and age = #{age}
  17. </select>
  18. <!--查询name包含指定字符的数据-->
  19. <select id="getNameContain" parameterType="String" resultType="User">
  20. select * from demo_user where name like "%"#{str}"%"
  21. </select>
  22. <!--查询按照age>xx,并按照age和sex排序的数据-->
  23. <select id="toSort" resultType="User">
  24. select * from demo_user where age &gt; #{age} order by age asc ,sex desc
  25. </select>
  26. <!--根据name/age动态查询数据,如果name/age不为null则拼接where条件-->
  27. <select id="getByNameAge" resultType="User">
  28. select * from demo_user
  29. <if test="name!=null">where name=#{name} <if test="age!=null">and age=#{age}</if></if>
  30. </select>
  31. <!--随机查询5个id的数据-->
  32. <select id="getByIdS" resultType="User">
  33. select * from demo_user where id in
  34. <foreach collection="array" index="index" item="id" open="(" separator="," close=")">#{id}</foreach>
  35. </select>
  36. <!--查询指定sex=xx和age>xx的数据-->
  37. <select id="getBySexAge" resultType="User">
  38. select * from demo_user where sex = #{sex} and age &gt; #{age}
  39. </select>
  40. <!--根据name更新数据-->
  41. <update id="updateByName">
  42. update demo_user set name = #{aftername},age = #{age} where name = #{beforename}
  43. </update>
  44. <!--根据id主键删除单个数据-->
  45. <delete id="delById">
  46. delete from demo_user where id = #{id}
  47. </delete>
  48. <!--根据id主键删除多条数据-->
  49. <delete id="delByIdS">
  50. delete from demo_user where id in
  51. <foreach collection="arr" item="id" index="index" open="(" separator="," close=")">#{id}</foreach>
  52. </delete>
  53. <!--根据指定name删除数据-->
  54. <delete id="delByName">
  55. delete from demo_user where name = #{name}
  56. </delete>
  57. <!--根据指定id主键更新数据-->
  58. <update id="updateById1">
  59. update demo_user set name = #{name},sex = #{sex},age = #{age} where id = #{id}
  60. </update>
  61. <!--插入数据-->
  62. <insert id="insertInto">
  63. insert into demo_user (name,sex,age) values (#{name},#{sex},#{age})
  64. </insert>
  65. </mapper>

 创建application.yml文件,里面包含要连接数据库、驱动器、用户名与密码等配置信息

  1. server:
  2. port: 8090
  3. spring:
  4. datasource:
  5. driver-class-name: com.mysql.cj.jdbc.Driver
  6. url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
  7. username: root
  8. password: root
  9. #如果数据库密码以数字0开头 则必须使用""号包裹
  10. #password: "01234"
  11. #SpringBoot整合Mybatis配置
  12. #定义别名包:实现对象映射
  13. #只做增强不做改变
  14. mybatis-plus:
  15. type-aliases-package: com.jt.pojo
  16. #映射文件加载路径
  17. mapper-locations: classpath:/mybatisplus/*.xml
  18. #开启驼峰映射
  19. configuration:
  20. map-underscore-to-camel-case: true
  21. #不打印日志
  22. debug: false
  23. logging:
  24. level:
  25. com.jt.mapper: debug

3.2.4 创建Mapper层接口文件

包路径要与xml配置文件的namespace值要一致,方法名和返回值类型分别要与xml文件的id和返回值类型要一致。

  1. package com.jt.mapper;
  2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  3. import com.jt.pojo.User;
  4. import org.apache.ibatis.annotations.Param;
  5. import java.util.List;
  6. //继承接口时必须添加泛型对象,否则映射表报错
  7. public interface UserMapper extends BaseMapper<User> {
  8. //查询表中所有数据
  9. List<User> getAll();
  10. //询指定id的数据
  11. List<User> getById(Integer id);
  12. //查询指定sex和age的数据
  13. List<User> getByAgeSex(@Param("sex") String sex,@Param("age") Integer age);
  14. //查询name包含指定字符的数据
  15. List<User> getNameContain(String str);
  16. //按年龄排序和性别排序
  17. List<User> toSort(Integer age);
  18. //根据name/age动态查询数据,如果name/age不为null则拼接where条件
  19. List<User> getByNameAge(@Param("name") String name, @Param("age") Integer age);
  20. //随机查询5个id的数据
  21. List<User> getByIdS(@Param("array") int[] id);
  22. //查询按照age>xx,并按照age和sex排序的数据
  23. List<User> getBySexAge(@Param("sex") String sex,@Param("age") Integer age);
  24. //根据name更新数据
  25. void updateByName(@Param("beforename") String beforename,@Param("aftername") String aftername,@Param("age") Integer age);
  26. //根据id主键删除单个数据
  27. void delById(Integer id);
  28. //根据id主键删除多条数据
  29. void delByIdS(@Param("arr") Integer[] id);
  30. //根据指定name删除数据
  31. void delByName(String name);
  32. //根据指定id主键更新数据
  33. void updateById1(@Param("id") Integer id,@Param("name") String name,@Param("sex") String sex,@Param("age") Integer age);
  34. //插入数据(主键自增)
  35. void insertInto(@Param("name") String name,@Param("sex") String sex,@Param("age") Integer age);
  36. }

3.3 对比测试

3.3.1 创建测试类

注释里的(MP)代表该方法是使用MybatisPlus实现的。

说明:以下的所有方法都经过测试,并未出现错误结果,请根据实际情况向对应方法中传入合适参数。

  1. package com.jt;
  2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  3. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  4. import com.jt.mapper.UserMapper;
  5. import com.jt.pojo.User;
  6. import org.junit.jupiter.api.Test;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.util.StreamUtils;
  10. import org.springframework.util.StringUtils;
  11. import java.util.ArrayList;
  12. import java.util.Arrays;
  13. import java.util.List;
  14. /*
  15. * 测试注解只能在test包下使用
  16. * 此注解表示可以从spring容器里面拿对象
  17. * */
  18. @SpringBootTest
  19. public class TestSpringBoot {
  20. @Autowired
  21. private UserMapper userMapper;//代理对象
  22. @Test//查询表中所有数据
  23. public void testGetAll(){
  24. // System.out.println(userMapper.getClass());
  25. List<User> userList = userMapper.getAll();
  26. System.out.println(userList);
  27. }
  28. @Test//查询指定id的数据
  29. public void testGetById(){
  30. System.out.println(userMapper.getById(50));
  31. }
  32. @Test//(MP)查询指定id的数据
  33. public void getByID(){
  34. User user = userMapper.selectById(1);
  35. System.out.println(user);
  36. }
  37. @Test//查询指定sex和age的数据
  38. public void testGetByAgeSex(){
  39. System.out.println(userMapper.getByAgeSex("男",18));
  40. }
  41. @Test//(MP)查询指定sex和age的数据
  42. public void getByAS(){
  43. User user = new User();
  44. user.setSex("女").setAge(18);
  45. QueryWrapper queryWrapper = new QueryWrapper(user);
  46. List<User> userList = userMapper.selectList(queryWrapper);
  47. System.out.println(userList);
  48. }
  49. @Test//查询指定sex=xx和age>xx的数据
  50. public void getBySexAge(){
  51. List<User> userlist = userMapper.getBySexAge("男", 18);
  52. System.out.println(userlist);
  53. }
  54. @Test//(MP)查询指定sex=xx和age>xx的数据
  55. public void getBygtAS(){
  56. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  57. queryWrapper.gt("age", 18).eq("sex","女");
  58. List<User> userList = userMapper.selectList(queryWrapper);
  59. System.out.println(userList);
  60. }
  61. @Test//查询name包含指定字符的数据
  62. public void testGetNameContain(){
  63. System.out.println(userMapper.getNameContain("孙"));
  64. }
  65. @Test//(MP)查询name包含指定字符的数据
  66. public void getContain1(){
  67. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  68. queryWrapper.like("name", "君");
  69. List<User> userList = userMapper.selectList(queryWrapper);
  70. System.out.println(userList);
  71. }
  72. @Test//查询按照age>xx,并按照age和sex排序的数据
  73. public void testToSort(){
  74. System.out.println(userMapper.toSort(18));
  75. }
  76. @Test//(MP)查询按照age>xx,并按照age和sex排序的数据
  77. public void testOrderBy(){
  78. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  79. queryWrapper.gt("age", 18).orderByDesc("age").orderByAsc("sex");
  80. List<User> userList = userMapper.selectList(queryWrapper);
  81. System.out.println(userList);
  82. }
  83. @Test//随机查询5个id的数据
  84. public void testGetByIdS(){
  85. int[] arr = {5,6,7,8,9};
  86. System.out.println(userMapper.getByIdS(arr));
  87. }
  88. @Test//(MP)随机查询5个id的数据
  89. public void testIn(){
  90. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  91. queryWrapper.in("id",1,3,5,7,6);
  92. List<User> userList = userMapper.selectList(queryWrapper);
  93. System.out.println(userList);
  94. Integer[] ids = new Integer[]{1,3,5,7,6};
  95. List<Integer> idList = Arrays.asList(ids);
  96. List<User> userList1 = userMapper.selectBatchIds(idList);
  97. System.out.println(userList1);
  98. }
  99. @Test//根据name/age动态查询数据,如果name/age不为null则拼接where条件
  100. public void testGetByNameAge(){
  101. System.out.println(userMapper.getByNameAge("如花",null));
  102. }
  103. @Test//(MP)根据name/age动态查询数据,如果name/age不为null则拼接where条件
  104. public void testSelectNS(){
  105. String name = "小乔";
  106. String sex = "女";
  107. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  108. boolean nameFlag = StringUtils.hasLength(name);
  109. boolean sexFlag = StringUtils.hasLength(sex);
  110. queryWrapper.eq(nameFlag,"name", name).eq(sexFlag,"sex", sex);
  111. List<User> userList = userMapper.selectList(queryWrapper);
  112. System.out.println(userList);
  113. }
  114. @Test//根据name更新数据
  115. public void updateByName(){
  116. userMapper.updateByName("云英", "吴饭饭", 18);
  117. System.out.println("成功");
  118. }
  119. @Test//(MP)根据name更新数据
  120. public void updateTest(){
  121. User user = new User();
  122. user.setAge(100).setName("祝君好运");
  123. UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
  124. updateWrapper.eq("name", "吴反反");
  125. userMapper.update(user,updateWrapper);
  126. }
  127. @Test//根据id主键删除单个数据
  128. public void delById(){
  129. userMapper.delById(235);
  130. System.out.println("成功");
  131. }
  132. @Test//(MP)根据id主键删除单个数据
  133. public void testDel(){
  134. userMapper.deleteById(232);
  135. System.out.println("成功");
  136. }
  137. @Test//根据id主键删除多条数据
  138. public void delByIds(){
  139. Integer[] arr = {233,234};
  140. userMapper.delByIdS(arr);
  141. System.out.println("成功");
  142. }
  143. @Test//(MP)根据id主键删除多条数据
  144. public void testDelIds(){
  145. Integer[] ids = new Integer[]{231,227};
  146. List<Integer> integers = Arrays.asList(ids);
  147. userMapper.deleteBatchIds(integers);
  148. System.out.println("成功");
  149. }
  150. @Test//根据指定name删除数据
  151. public void delByName(){
  152. userMapper.delByName("吴饭饭");
  153. System.out.println("成功");
  154. }
  155. @Test//(MP)根据指定name删除数据
  156. public void testDelNA(){
  157. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  158. queryWrapper.eq("name", "吴亦凡").eq("age", 30);
  159. userMapper.delete(queryWrapper);
  160. System.out.println("成功");
  161. }
  162. @Test//根据指定id主键更新数据
  163. public void updateById1(){
  164. userMapper.updateById1(196, "饭饭", "男", 1000);
  165. System.out.println("成功");
  166. }
  167. @Test//(MP)根据指定id主键更新数据
  168. public void updateByIdMP(){
  169. User user = new User();
  170. user.setName("云英").setSex("男").setAge(16).setId(196);
  171. userMapper.updateById(user);
  172. System.out.println("成功");
  173. }
  174. @Test//插入数据
  175. public void insertUser(){
  176. userMapper.insertInto("凡凡", "男", 222);
  177. System.out.println("成功");
  178. }
  179. @Test//(MP)插入数据
  180. public void testInsert(){
  181. User user = new User();
  182. user.setId(555).setName("吴亦凡").setAge(30).setSex("男");
  183. userMapper.insert(user);
  184. System.out.println("成功");
  185. }
  186. }

3.3.2 MybatisPlus实现原理

  1. 用户执行User对象入库操作 userMapper.insert(user);
  2. 由于接口方法中需要传递泛型对象,则根据用户配置查找对应的泛型对象
  3. 根据用户的接口获取Mapper接口的父级接口BaseMapper,根据BaseMapper中的泛型对象 获取信息User.class类型
  4. 根据User.class 动态获取@TableName(“demo_user”) 获取对象对应的表名.之后通过@TableField(“name”)绑定与之对应的字段. 至此对象与表完成了映射.
  5. 根据上述的映射关系,动态的拼接Sql语句.
  6. MP将动态生成的Sql交给Mybatis执行最终实现数据入库操作!!!

为什么不建议你使用Mybatis-plus

代码整洁本身是为了降低修改成本的,MP本末倒置。
整洁的代码意味着阅读代码的时间成本降低,但是如果使用MP,在你阅读service层代码时,还会看到在代码中拼装SQL执行条件的部分。这样一来,service层代码和数据库访问层代码混淆在一起,让程序员很难专注的关心某一细节。常见的SQL操作MP可以通过Wrapper构造SQL执行条件,程序员就看不到一条条SQL语句,而阅读和检查SQL逻辑是比较耗费精力的事,MP只不过是以后期维护成本为代价换取开发时貌似整洁的优势。

SQL执行错误是最容易修改的错误
如果你使用纯Mybatis相比MP会更容易爆出SQL执行错误。其实大可不必太在乎这个问题,如果是SQL执行逻辑有问题,那不管MP还是Mybatis都会报错。如果是SQL语法错误,由于SQL语法错误在Java开发中错误日志非常显眼,所以你可以通过复制日志中报错的SQL然后代码全局搜索快速定位出错位置,而且SQL语法错误基本都是字段名写错或者执行条件顺序错误,这都是非常容易修改的BUG。

纯Mybatis具有更好的代码复用性
比如,我要查询班级id为7,的所有班干部同学。你在纯Mybatis中会一次性将SQL写进XML文件中,如果在项目中这条SQL需要调用N次,你只需要在这N个地方都传参调用即可。但如果用了MP,你需要将相同的代码复制N次。
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/790641
推荐阅读
相关标签
  

闽ICP备14008679号