1. MybatisPlus
1.1 业务需求
Mybatis缺点:
- 1.Mybatis操作数据库的过程中,需要编辑大量的sql语句.无论该sql是否复杂或者简单.
- 2.Mybatis操作时在xml配置文件中需要额外记忆单独的标签.
需求:能否实现单表操作的CRUD的全自动的实现.能否实现真正的ORM映射?
1.2ORM
要求:利用面向对象的方式操作数据库 特点:
1.操作数据库的面向对象.
userMapper.insert(user对象); ------->自己编辑sql语句
2.查询数据库的面向对象.
userMapper.selectByWhere(user对象); ------>动态的生成Sql------>自动实现结果集封装.
1.3ORM实现单表操作原理
要求:实现单表的自动的CRUD操作 例子:
1 User user = new Uesr(); 2• user.setId(xx).setName(xx).setAge(xx).setSex(xx); 3• userMapper.insertUser(user);
框架内部实现过程:
核心:数据库只能识别sql语句.框架需要将对象转化为sql.
核心配置:
1.User对象与数据库的表 一一映射!
解决方法: 自定义注解标识表与对象的关系
2.User对象的属性与数据表中的字段一一映射!
解决方法:自定义注解完成属性与字段的映射
3.将CURD的方法进行统一的定义.形成工具API接口
解决方法:利用公共的mapper接口 BaseMapper,在其中定义几乎所有的单表的CURD操作.
4.将接口方法按照数据库方式转化为特定的sql语句.
1.用户的调用 userMapper.insert(user)
2.拼接特定的sql:
insert into 表名(字段名......) values(属性值......);
一般利用反射技术,可以通过对象或者有关对象的全部信息(注解,属性,属性值)
1.4 MybatisPlus介绍(MP)
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
1.5 MybatisPlus特性
-
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
-
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
-
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
-
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
-
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
-
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
-
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
-
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
-
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
-
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
-
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
-
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
1.6 MybatisPlus的实际入门操作
1.6.1导入jar包
==最主要的jar包==
1<!--spring整合mybatis-plus --> 2 <dependency> 3 <groupId>com.baomidou</groupId> 4 <artifactId>mybatis-plus-boot-starter</artifactId> 5 <version>3.2.0</version> 6 </dependency>
==本次所需的其余jar包==
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-web</artifactId> 4 </dependency> 5 6 <dependency> 7 <groupId>org.springframework.boot</groupId> 8 <artifactId>spring-boot-starter-test</artifactId> 9 <scope>test</scope> 10 </dependency> 11 12 <!--添加属性注入依赖 --> 13 <dependency> 14 <groupId>org.springframework.boot</groupId> 15 <artifactId>spring-boot-configuration-processor</artifactId> 16 <optional>true</optional> 17 </dependency> 18 19 <!--引入插件lombok 自动的set/get/构造方法插件 --> 20 <dependency> 21 <groupId>org.projectlombok</groupId> 22 <artifactId>lombok</artifactId> 23 </dependency> 24 25 <!--支持热部署 --> 26 <dependency> 27 <groupId>org.springframework.boot</groupId> 28 <artifactId>spring-boot-devtools</artifactId> 29 </dependency> 30 31 <!--引入数据库驱动 --> 32 <dependency> 33 <groupId>mysql</groupId> 34 <artifactId>mysql-connector-java</artifactId> 35 <scope>runtime</scope> 36 </dependency> 37 38 <!--springBoot数据库连接 --> 39 <dependency> 40 <groupId>org.springframework.boot</groupId> 41 <artifactId>spring-boot-starter-jdbc</artifactId> 42 </dependency>
6.2 编辑POJO文件
注意如果没有lombok插件可以在 https://blog.csdn.net/XING_Gou/article/details/104316560中安装Lombok插件
1package com.jt.demo.pojo; 2 3import com.baomidou.mybatisplus.annotation.IdType; 4import com.baomidou.mybatisplus.annotation.TableId; 5import com.baomidou.mybatisplus.annotation.TableName; 6 7import lombok.Data; 8import lombok.experimental.Accessors; 9 10@Data 11@Accessors(chain=true) //链式加载 12@TableName //标识对象与表之间的关联关系 13public class User { 14 //简化步骤:如果属性的名称与映射的名称一致,则可以省略不写 15 @TableId(type=IdType.AUTO) //定义主键 主键自增 16 private Integer id; 17 //对象的属性与表中的字段. 18 //@TableField(value="name") 19 private String name; 20 private Integer age; 21 private String sex; 22 23}
数据库
1DROP DATABASE IF EXISTS `jtdb`; 2CREATE DATABASE `jtdb` DEFAULT CHARACTER SET utf8; 3USE `jtdb`; 4 5/*Table structure for table `user` */ 6 7DROP TABLE IF EXISTS `user`; 8 9CREATE TABLE `user` ( 10 `id` int(11) NOT NULL AUTO_INCREMENT, 11 `name` char(40) DEFAULT NULL, 12 `age` int(11) DEFAULT NULL, 13 `sex` char(40) DEFAULT NULL, 14 PRIMARY KEY (`id`), 15 KEY `cc` (`id`) 16) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8; 17 18/*Data for the table `user` */ 19 20insert into `user`(`id`,`name`,`age`,`sex`) values (1,'黑熊精',4000,'男'),(2,'鲤鱼精',5000,'男'),(3,'金角大王',3000,'男'),(4,'银角大王',4000,'男'),(5,'唐僧',30,'男'),(6,'悟空',501,'男'),(7,'白龙驴',2000,'男'),(8,'八戒',502,'男'),(9,'沙悟净',503,'男'),(11,'小乔',17,'女'),(12,'貂蝉',18,'女'),(16,'黄月英',18,'女'),(17,'孙尚香',18,'女'),(18,'甄姬c',20,'女'),(21,'孙尚香D',18,'女'),(22,'刘备',40,'男'),(23,'陆逊',33,'男'),(24,'陆逊',33,'男'),(25,'关羽',40,'男'),(27,'阿科',20,'女'),(31,'王昭君',19,'女'),(38,'貂蝉',18,'女'),(39,'西施',18,'女'),(40,'严真煌',16,'女'),(41,'白骨精',18,'女'),(43,'小乔',19,'男'),(44,'大乔',19,'女'),(46,'不知火舞',18,'女'),(49,'小兰兰',18,'男'),(50,'柳鹏林',18,'男'),(51,'妲己',18,'男'),(52,'如花',17,'男');
6.3 继承共同的API接口
public interface UserMapper extends BaseMapper<User>{...}
编辑YML配置
1server: 2 port: 8090 #标识端口号信息 3 servlet: 4 context-path: / 5spring: 6 datasource: 7 driver-class-name: com.mysql.jdbc.Driver 8 url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true 9 username: root 10 password: root 11 12#SpringBoot整合Mybatis-plus配置信息 13mybatis-plus: 14 #定义别名包 只要定义了别名包,则程序中resultType可以省略包路径 15 type-aliases-package: com.jt.demo.pojo 16 #配置文件的资源加载路径 17 mapper-locations: classpath:/mybatis/mappers/*.xml 18 #开启驼峰映射 19 configuration: 20 map-underscore-to-camel-case: true
6.5 入门案例测试
1@RunWith(SpringRunner.class) //注意测试文件的位置 必须在主文件加载包路径下 2@SpringBootTest 3public class TestMP { 4 5 //注入mapper接口 6 @Autowired 7 private UserMapper userMapper; 8 /** 9 * 1.入门案例 10 * 要求:查询全部的用户信息 不需要写where条件 11 * 注意事项:利用MP的方法和自己的接口方法 名称不能重复. 12 * 13 * 参数说明:queryWrapper 动态生成sql语句中的where条件 14 */ 15 @Test 16 public void test01() { 17 List<User> userList = userMapper.selectList(null); 18 System.out.println(userList); 19 } 20}
1.7Mybatis案例
1.selectBatchIds
1 /** 2 * 练习1: 查询id信息为1,3,4,5,6用户数据 3 * sql: select * from user where id in (1,2,3,4,5,6); 4 * 思考:id可以利用数组进行接收 利用数组查询数据 5 */ 6 7 @Test 8 public void test02() { 9 10 List<Integer> idList = new ArrayList<Integer>(); 11 idList.add(1); 12 idList.add(3); 13 idList.add(4); 14 idList.add(5); 15 idList.add(6); 16 //以对象的方式进行数据库操作 17 List<User> userList = userMapper.selectBatchIds(idList); 18 System.out.println(userList); 19 }
2. selectByMap
说明:根据字段查询用户信息
1 /** 2 * 练习2: 根据name="黑熊精" age="3000"查询数据信息 3 * SelectByMap:根据具体的字段查询用户信息. 4 * sql语句: select * from user where name="黑熊精" and age=3000 5 * 规则:默认使用and连接符. 6 */ 7 8 @Test 9 public void test03() { 10 Map<String,Object> map = new HashMap<>(); 11 //key="字段名称" value="字段值" 12 map.put("name", "黑熊精"); 13 map.put("age", 3000); 14 List<User> userList = userMapper.selectByMap(map); 15 System.out.println(userList); 16 17 }
3. 条件构造器查询
1/** 2 * 4.name属性中包含"精"的数据,并且为女性 3 * sql: SELECT * FROM USER WHERE NAME LIKE "%精%" AND sex = "女" 4 * queryWrapper: 条件构造器 5 * 作用 动态拼接sql的where条件 6 * 逻辑运算符: >gt , <lt, =eq, >=ge, <= le 7 */ 8 9 @Test 10 public void test04() { 11 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); 12 queryWrapper.like("name", "精") 13 .eq("sex", "女"); 14 List<User> userList = userMapper.selectList(queryWrapper); 15 System.out.println(userList); 16 17 }
4. Between-and
1 /** 2 * 查询年龄在18-35之间的女性用户. 3 * sql: SELECT * FROM USER WHERE age BETWEEN 18 AND 35 AND sex ="女"; 4 */ 5 @Test 6 public void test05() { 7 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); 8 queryWrapper.between("age", 18, 35) 9 .eq("sex", "女"); 10 List<User> userList = userMapper.selectList(queryWrapper); 11 System.out.println(userList); 12 } 13
5. order by
1/** 2 * 条件: 查询年龄大于100岁的,并且按照年龄降序排列, 3 * 如果年龄相同按照Id降序排列. 4 * sql:SELECT * FROM USER WHERE age > 100 ORDER BY age DESC,id DESC; 5 */ 6 @Test 7 public void test06() { 8 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); 9 queryWrapper.gt("age", 100) 10 .orderByDesc("age","id"); 11 List<User> userList = userMapper.selectList(queryWrapper); 12 System.out.println(userList); 13 }
6. like练习
1/** 2 * 条件: 查询名称以"乔"结尾的,并且性别为女,并且age小于30岁.按照年龄降序排列. 3 * SQL: 4 * SELECT * FROM USER WHERE (NAME LIKE "%乔" AND sex="女" 5AND age < 30) ORDER BY age DESC; 6 */ 7 @Test 8 public void test07(){ 9 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); 10 queryWrapper.likeLeft("name","乔") 11 .eq("sex", "女") 12 .lt("age", 30) 13 .orderByDesc("age"); 14 List<User> userList = userMapper.selectList(queryWrapper); 15 System.out.println(userList); 16 }
7.inSql
说明:适用于子查询
1/** 2 * 查询age < 100岁的用户,并且性别与name="孙尚香"的性别相同的的用户数据. 3 * 分析: age<100 sex=男/女 4 * sql:SELECT * FROM USER WHERE age < 100 AND 5 sex in( 6 SELECT sex FROM USER WHERE NAME = "孙尚香" 7 ) 8 */ 9 @Test 10 public void test08(){ 11 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); 12 queryWrapper.lt("age",100) 13 .inSql("sex", "select sex from user where name ='孙尚香'"); 14 List<User> userList = userMapper.selectList(queryWrapper); 15 System.out.println(userList); 16 }
8.select
1/** 2 * 需求: 有时可能不需要查询全部的数据库的表字段 3 * 查询age为18岁的用户的名称和id. 4 * select:挑选字段的属性. 5 * 查询结果:User(id=12, name=貂蝉, age=null, sex=null) 6 */ 7 @Test 8 public void test09() { 9 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); 10 queryWrapper.select("name","id") 11 .eq("age", 18); 12 List<User> userList = userMapper.selectList(queryWrapper); 13 System.out.println(userList); 14 }
9.condition
1/** 2 * 条件判断 3 * 以name和sex不为null的数据当做where条件. 4 * condition作用: 5 * 判断参数是否拼接为where条件 6 * 结果true, 动态拼接参数 7 * 结果false, 参数不会动态拼接 8 * 应用场景: 9 * 接收前台的参数时,参数可能为null或者其他的数值类型时 10 * 需要添加判断. 11 * 业务需求: 12 * 如果age>18时,才能查询年龄 13 */ 14 @Test 15 public void test10() { 16 String name = null; 17 int age = 18; 18 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); 19 //name属性的值,不为null时,才会拼接where条件 20 queryWrapper.eq(!StringUtils.isEmpty(name), "name", name); 21 queryWrapper.eq(age>18, "age", age); 22 List<User> userList = userMapper.selectList(queryWrapper); 23 System.out.println(userList); 24 }
10. 根据对象查询
1/** 2 * 根据对象查询数据库 3 * 条件:根据对象中不为null的属性充当where条件 4 * 需求:查询age=18的用户信息 性别=女 5 * 说明:利用对象的方式查询时,逻辑运算符都是"="号 6 */ 7 @Test 8 public void test11() { 9 User user = new User(); 10 user.setAge(18) 11 .setSex("女"); 12 QueryWrapper<User> queryWrapper = new QueryWrapper<>(user); 13 List<User> userList = userMapper.selectList(queryWrapper); 14 System.out.println(userList); 15 } 16 17
11. selectObjs
说明:只查询主键信息(第一列)数据
1/** 2 * 需求:只查询主键的信息. 3 * 类比: select 4 * sql: SELECT id FROM USER where age >18 5 */ 6 @Test 7 public void test12() { 8 QueryWrapper<User> queryWrapper2 = new QueryWrapper<User>(); 9 queryWrapper2.select("id"); 10 //查询的List<User>对象信息 11 userMapper.selectList(queryWrapper2); 12 QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); 13 queryWrapper.gt("age", 18); 14 //只查询主键信息 15 List<Object> idList = userMapper.selectObjs(queryWrapper); 16 System.out.println(idList); 17 } 18
12.selectMaps
说明:获取任意字段的数据信息
1/** 2 * 获取任意的字段信息 3 * 需求:查询用户信息 只想获取id和name的值.不想获取age/sex 4 * sql: select id,name from user where age > 18; 5 */ 6 @Test 7 public void test13() { 8 QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); 9 queryWrapper.select("id","name") 10 .gt("age", 18); 11 //获取全部的对象信息 12 List<User> userList = userMapper.selectList(queryWrapper); 13 //获取字段的信息 14 List<Map<String,Object>> listMap = userMapper.selectMaps(queryWrapper); 15 System.out.println(userList); 16 System.out.println(listMap); 17 }
13. 新增用户
1@Test 2 public void test14() { 3 User user = new User(); 4 user.setName("外国人永久居住权") 5 .setSex("男") 6 .setAge(30); 7 userMapper.insert(user); 8 }
14.删除用户
1/** 2 * 删除用户信息 3 */ 4 5 @Test 6 public void test15() { 7 QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); 8 queryWrapper.eq("name", "外国人永久居住权"); 9 //根据多个条件 删除用户数据. 10 userMapper.delete(queryWrapper); 11 //根据集合中的数据.批量删除用户信息 12 Integer[] ids = {2000,2001}; 13 List<Integer> idList = Arrays.asList(ids); 14 userMapper.deleteBatchIds(idList); 15 //id 代表主键信息 根据主键进行删除. 16 userMapper.deleteById(2000); 17 18 //挑选字段和属性进行删除. 19 Map<String,Object> columnMap = new HashMap<String, Object>(); 20 columnMap.put("name", "疫情"); 21 userMapper.deleteByMap(columnMap); 22 }
15. 修改操作
1 /** 2 * 更新操作 3 * updateById: 根据主键信息修改数据. 4 * 主键信息必须添加充当where条件, 5 * 根据对象中不为null的数据,充当set条件. 6 * sql: update user set name="xx",age=xxx,sex=xx where id=23 7 * 8 * update方法说明: 9 * 参数1:entity 修改后的数据结果 10 * 参数2:updateWrapper 修改的条件构造器 11 * 案例: 12 * 将杨颖改为范冰冰 修改年龄/性别 13 * sql : update user set name="xxxx",age=xxx,sex=xxx 14 * where name = "杨颖"; 15 * 16 */ 17 @Test 18 public void test16() { 19 User user = new User(); 20 user.setId(23).setName("潘凤").setAge(35).setSex("男"); 21 userMapper.updateById(user); 22 23 User user2 = new User(); 24 user2.setName("范冰冰").setAge(40).setSex("女"); 25 UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); 26 updateWrapper.eq("name", "杨颖"); 27 userMapper.update(user2, updateWrapper); 28 }