Mybatis-Plus入门案例、以及为什么不建议使用MP?
目录
目录
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调用流程
- Spring容器为接口创建代理对象. Spring容器启动对象立即创建
- 根据 @Autowired 注解动态注入Mapper接口的代理对象
- 用户通过Mapper接口调用方法.(执行业务操作)
- 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中导入相关依赖包
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.2</version><relativePath/> <!-- lookup parent from repository --></parent><properties><java.version>1.8</java.version><!--跳过测试类打包--><skipTests>true</skipTests></properties><!--原则:按需导入--><dependencies><dependency><groupId>org.springframework.boot</groupId><!--springboot启动项(器),在包的内部springboot已经完成了项目的“整合”(配置)用户拿来就能用--><artifactId>spring-boot-starter-web</artifactId></dependency><!--数据库驱动--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!--springboot数据库连接--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><!--springboot项目与Maven整合的一个插件可以通过插件 执行项目打包/测试/文档生成等操作注意事项:该插件不能省略,如果省略启动时报错(省略时)项目发布时:java -jar xxxx.jar 报错没有主清单信息!!--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
3.2.2 创建对象关系映射User类
注意user类是与demo_user表对应,属性与字段对应。
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data//使用了lombok插件,不用手写set、get、tostring等方法
@Accessors(chain = true)
@TableName("demo_user")
public class User implements Serializable {//ID代表主键,不是id字段@TableId(type=IdType.AUTO)//主键自增//@TableField("name")//如果属性与字段同名(包括驼峰规则)注解可以省略private Integer id;private String name;private Integer age;private String sex;
}
3.2.3 创建配置文件
创建UserMapper.xml文件,里面包含大量的SQL语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jt.mapper.UserMapper"><!--查询表中所有数据--><select id="getAll" resultType="User">select * from demo_user</select><!--查询指定id的数据--><select id="getById" resultType="User">select * from demo_user where id = #{id}</select><!--查询指定sex和age的数据--><select id="getByAgeSex" resultType="User">select * from demo_user where sex = #{sex} and age = #{age}</select><!--查询name包含指定字符的数据--><select id="getNameContain" parameterType="String" resultType="User">select * from demo_user where name like "%"#{str}"%"</select><!--查询按照age>xx,并按照age和sex排序的数据--><select id="toSort" resultType="User">select * from demo_user where age > #{age} order by age asc ,sex desc</select><!--根据name/age动态查询数据,如果name/age不为null则拼接where条件--><select id="getByNameAge" resultType="User">select * from demo_user<if test="name!=null">where name=#{name} <if test="age!=null">and age=#{age}</if></if></select><!--随机查询5个id的数据--><select id="getByIdS" resultType="User">select * from demo_user where id in<foreach collection="array" index="index" item="id" open="(" separator="," close=")">#{id}</foreach></select><!--查询指定sex=xx和age>xx的数据--><select id="getBySexAge" resultType="User">select * from demo_user where sex = #{sex} and age > #{age}</select><!--根据name更新数据--><update id="updateByName">update demo_user set name = #{aftername},age = #{age} where name = #{beforename}</update><!--根据id主键删除单个数据--><delete id="delById">delete from demo_user where id = #{id}</delete><!--根据id主键删除多条数据--><delete id="delByIdS">delete from demo_user where id in<foreach collection="arr" item="id" index="index" open="(" separator="," close=")">#{id}</foreach></delete><!--根据指定name删除数据--><delete id="delByName">delete from demo_user where name = #{name}</delete><!--根据指定id主键更新数据--><update id="updateById1">update demo_user set name = #{name},sex = #{sex},age = #{age} where id = #{id}</update><!--插入数据--><insert id="insertInto">insert into demo_user (name,sex,age) values (#{name},#{sex},#{age})</insert>
</mapper>
创建application.yml文件,里面包含要连接数据库、驱动器、用户名与密码等配置信息
server:port: 8090spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=trueusername: rootpassword: root#如果数据库密码以数字0开头 则必须使用""号包裹#password: "01234"#SpringBoot整合Mybatis配置
#定义别名包:实现对象映射
#只做增强不做改变
mybatis-plus:type-aliases-package: com.jt.pojo#映射文件加载路径mapper-locations: classpath:/mybatisplus/*.xml#开启驼峰映射configuration:map-underscore-to-camel-case: true
#不打印日志
debug: false
logging:level:com.jt.mapper: debug
3.2.4 创建Mapper层接口文件
包路径要与xml配置文件的namespace值要一致,方法名和返回值类型分别要与xml文件的id和返回值类型要一致。
package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
//继承接口时必须添加泛型对象,否则映射表报错
public interface UserMapper extends BaseMapper<User> {//查询表中所有数据List<User> getAll();//询指定id的数据List<User> getById(Integer id);//查询指定sex和age的数据List<User> getByAgeSex(@Param("sex") String sex,@Param("age") Integer age);//查询name包含指定字符的数据List<User> getNameContain(String str);//按年龄排序和性别排序List<User> toSort(Integer age);//根据name/age动态查询数据,如果name/age不为null则拼接where条件List<User> getByNameAge(@Param("name") String name, @Param("age") Integer age);//随机查询5个id的数据List<User> getByIdS(@Param("array") int[] id);//查询按照age>xx,并按照age和sex排序的数据List<User> getBySexAge(@Param("sex") String sex,@Param("age") Integer age);//根据name更新数据void updateByName(@Param("beforename") String beforename,@Param("aftername") String aftername,@Param("age") Integer age);//根据id主键删除单个数据void delById(Integer id);//根据id主键删除多条数据void delByIdS(@Param("arr") Integer[] id);//根据指定name删除数据void delByName(String name);//根据指定id主键更新数据void updateById1(@Param("id") Integer id,@Param("name") String name,@Param("sex") String sex,@Param("age") Integer age);//插入数据(主键自增)void insertInto(@Param("name") String name,@Param("sex") String sex,@Param("age") Integer age);
}
3.3 对比测试
3.3.1 创建测试类
注释里的(MP)代表该方法是使用MybatisPlus实现的。
说明:以下的所有方法都经过测试,并未出现错误结果,请根据实际情况向对应方法中传入合适参数。
package com.jt;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*
* 测试注解只能在test包下使用
* 此注解表示可以从spring容器里面拿对象
* */
@SpringBootTest
public class TestSpringBoot {@Autowiredprivate UserMapper userMapper;//代理对象@Test//查询表中所有数据public void testGetAll(){
// System.out.println(userMapper.getClass());List<User> userList = userMapper.getAll();System.out.println(userList);}@Test//查询指定id的数据public void testGetById(){System.out.println(userMapper.getById(50));}@Test//(MP)查询指定id的数据public void getByID(){User user = userMapper.selectById(1);System.out.println(user);}@Test//查询指定sex和age的数据public void testGetByAgeSex(){System.out.println(userMapper.getByAgeSex("男",18));}@Test//(MP)查询指定sex和age的数据public void getByAS(){User user = new User();user.setSex("女").setAge(18);QueryWrapper queryWrapper = new QueryWrapper(user);List<User> userList = userMapper.selectList(queryWrapper);System.out.println(userList);}@Test//查询指定sex=xx和age>xx的数据public void getBySexAge(){List<User> userlist = userMapper.getBySexAge("男", 18);System.out.println(userlist);}@Test//(MP)查询指定sex=xx和age>xx的数据public void getBygtAS(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.gt("age", 18).eq("sex","女");List<User> userList = userMapper.selectList(queryWrapper);System.out.println(userList);}@Test//查询name包含指定字符的数据public void testGetNameContain(){System.out.println(userMapper.getNameContain("孙"));}@Test//(MP)查询name包含指定字符的数据public void getContain1(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.like("name", "君");List<User> userList = userMapper.selectList(queryWrapper);System.out.println(userList);}@Test//查询按照age>xx,并按照age和sex排序的数据public void testToSort(){System.out.println(userMapper.toSort(18));}@Test//(MP)查询按照age>xx,并按照age和sex排序的数据public void testOrderBy(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.gt("age", 18).orderByDesc("age").orderByAsc("sex");List<User> userList = userMapper.selectList(queryWrapper);System.out.println(userList);}@Test//随机查询5个id的数据public void testGetByIdS(){int[] arr = {5,6,7,8,9};System.out.println(userMapper.getByIdS(arr));}@Test//(MP)随机查询5个id的数据public void testIn(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.in("id",1,3,5,7,6);List<User> userList = userMapper.selectList(queryWrapper);System.out.println(userList);Integer[] ids = new Integer[]{1,3,5,7,6};List<Integer> idList = Arrays.asList(ids);List<User> userList1 = userMapper.selectBatchIds(idList);System.out.println(userList1);}@Test//根据name/age动态查询数据,如果name/age不为null则拼接where条件public void testGetByNameAge(){System.out.println(userMapper.getByNameAge("如花",null));}@Test//(MP)根据name/age动态查询数据,如果name/age不为null则拼接where条件public void testSelectNS(){String name = "小乔";String sex = "女";QueryWrapper<User> queryWrapper = new QueryWrapper<>();boolean nameFlag = StringUtils.hasLength(name);boolean sexFlag = StringUtils.hasLength(sex);queryWrapper.eq(nameFlag,"name", name).eq(sexFlag,"sex", sex);List<User> userList = userMapper.selectList(queryWrapper);System.out.println(userList);}@Test//根据name更新数据public void updateByName(){userMapper.updateByName("云英", "吴饭饭", 18);System.out.println("成功");}@Test//(MP)根据name更新数据public void updateTest(){User user = new User();user.setAge(100).setName("祝君好运");UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();updateWrapper.eq("name", "吴反反");userMapper.update(user,updateWrapper);}@Test//根据id主键删除单个数据public void delById(){userMapper.delById(235);System.out.println("成功");}@Test//(MP)根据id主键删除单个数据public void testDel(){userMapper.deleteById(232);System.out.println("成功");}@Test//根据id主键删除多条数据public void delByIds(){Integer[] arr = {233,234};userMapper.delByIdS(arr);System.out.println("成功");}@Test//(MP)根据id主键删除多条数据public void testDelIds(){Integer[] ids = new Integer[]{231,227};List<Integer> integers = Arrays.asList(ids);userMapper.deleteBatchIds(integers);System.out.println("成功");}@Test//根据指定name删除数据public void delByName(){userMapper.delByName("吴饭饭");System.out.println("成功");}@Test//(MP)根据指定name删除数据public void testDelNA(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("name", "吴亦凡").eq("age", 30);userMapper.delete(queryWrapper);System.out.println("成功");}@Test//根据指定id主键更新数据public void updateById1(){userMapper.updateById1(196, "饭饭", "男", 1000);System.out.println("成功");}@Test//(MP)根据指定id主键更新数据public void updateByIdMP(){User user = new User();user.setName("云英").setSex("男").setAge(16).setId(196);userMapper.updateById(user);System.out.println("成功");}@Test//插入数据public void insertUser(){userMapper.insertInto("凡凡", "男", 222);System.out.println("成功");}@Test//(MP)插入数据public void testInsert(){User user = new User();user.setId(555).setName("吴亦凡").setAge(30).setSex("男");userMapper.insert(user);System.out.println("成功");}
}
3.3.2 MybatisPlus实现原理
- 用户执行User对象入库操作 userMapper.insert(user);
- 由于接口方法中需要传递泛型对象,则根据用户配置查找对应的泛型对象
- 根据用户的接口获取Mapper接口的父级接口BaseMapper,根据BaseMapper中的泛型对象 获取信息User.class类型
- 根据User.class 动态获取@TableName(“demo_user”) 获取对象对应的表名.之后通过@TableField(“name”)绑定与之对应的字段. 至此对象与表完成了映射.
- 根据上述的映射关系,动态的拼接Sql语句.
- 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次。
Mybatis-Plus入门案例、以及为什么不建议使用MP?相关推荐
- MyBatis-学习笔记02【02.Mybatis入门案例】
Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...
- MyBatisPlus(一)MyBatisPlus介绍和入门案例
文章目录 MyBatis-Plus 简介 特性 框架结构 入门案例 MyBatis-Plus 简介 MyBatis-Plus(简称MP)是一个MyBatis增强工具,在MyBatis的基础上只做增强不 ...
- mybatis的入门
mybatis的环境搭建 第一步:创建maven工程并导入坐标 第二步:创建实体类和dao的接口 第三步:创建Mybatis的主配置文件 ...
- mybatis基于注解的入门案例
mybatis基于注解的入门案例: 把IUserDao.xml移除,在dao接口的方法上使用@Select注解,并且指定SQL语句 同时需要在SqlMa ...
- Mybatis学习IDEA(1)-环境搭建以及入门案例
Mybatis的环境搭建: 第一步:创建Maven项目 new Project->Maven->next->GroupId(反写域名如:com.itheima)ArtifactID( ...
- MyBatis由浅入深学习总结之一:MyBatis入门案例
一.MyBatis简介 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名 ...
- MyBatis Plus简介和入门案例
简介 MyBatis-Plus(以下简称MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发.提高效率而生. 润物无声 只做增强不做改变,引入它不会对现有 ...
- (spingboot入门案例)SpingBoot整合mybatis(mySql)
仅供参考 目录结构: 环境: idea,mysql(8.0.29) 1.新建项目 1. 2.Project SDK选择自己对应的java版本 url选第二个,使用阿里的镜像:http://start. ...
- idea springmvc_IDEA搭建SSM(spring+springmvc+mybatis)Maven项目的入门案例
上一篇文章已经搭建好了SSM的框架,并且启动成功,今天来编写一下入门案例. 文章的主要内容: 1.hello world的编写 2.引入log4j,在控制台打印sql 3.增删改查的编写 一.在mys ...
- Mybatis(1)---入门篇单表查询
1.Mybatis介绍 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
最新文章
- bzoj3786星系探索 splay
- SVM中的Karush-Kuhn-Tucker条件和对偶问题
- 中国汽车脚垫市场消费趋势与营销渠道分析报告2022版
- JavaScript内核系列 第8章 面向对象的JavaScript(下)
- linux ftp 实例
- jenkins 基础配置安装(Ⅰ)
- 小米手机的专用计算机连接软件,详细教您小米手机怎么连接电脑
- 7620a无线中继模块(wisp)
- 关于软件测试的英语面试题,软件测试工程师英语面试题
- 后台得到ajax传来的参数,几种ajax传参数到后台获取的方法
- dalao的背包九讲
- 判断对象内的 属性是否为空
- Vue 使用特殊字体
- CommonUtils 工具类
- 爬杜蕾斯官方微博,内容太刺激了吧
- 【pandas问题】UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xca in position 0: invalid continuati
- python 不能被2,3整除的数字
- 高德地图添加安全密钥
- win10重装系统后连不上公司服务器,Win10电脑重装系统后不能上网怎么办?
- python三级_Python三级目录展示方法