MybatisPlus

1.MybatisPlus介绍

Mybatis-Plus是一个Mybais的增强工具,在Mybatis的基础上只做增强,不做改变,为简化开发、提高效率而生。

2.MybatisPlus新特性

  1. 无侵入:只做增强不做改变,引入它不会对现有工程产生影响。
  2. 损耗小:启动即会自动注入基本的CRUD,性能基本无损耗,直接面向对象操作
  3. 强大的CRUD操作:内置通用Mapper、通用Service,仅仅通过少量配置即可实现单表大部分CRUD操作,更有强大的条件构造器,满足各类使用需求
  4. 支持Lambda形式调用:通过Lambda表达式,方便的编写各类查询条件,无需再担心字段写错
  5. 支持主键自动生成:支持多达4种主键策略(内含分布式唯一ID生成器-Sequence),可自由配置,完美解决主键问题。
  6. 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大 的 CRUD 操作.
  7. 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  8. 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(自动帮你生成代码)
  9. 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同 于普通 List 查询
  10. 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、 Postgre、SQLServer 等多种数据库
  11. 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢 查询
  12. 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误 操作

3.JPA思想

JPA是Java Persistence API的简称,中文名java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE应用开发工作;其二,Sun希望整合ORM技术,实现天下归一

4.MybatisPlus快速入门

官网地址:https://baomidou.com/初始化工程

使用第三方组件:

  1. 导入对应的依赖
  2. 研究依赖如何配置
  3. 代码如何编写
  4. 提高扩展技术能力

步骤:

1.创建数据库 mybatis_plus

2.创建user表

 1 DROP TABLE IF EXISTS user;
 2 
 3 CREATE TABLE user
 4 (
 5     id BIGINT(20) NOT NULL COMMENT '主键ID',
 6     name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
 7     age INT(11) NULL DEFAULT NULL COMMENT '年龄',
 8     email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
 9     PRIMARY KEY (id)
10 );

3.插入数据

1 INSERT INTO user (id, name, age, email) VALUES
2 (1, 'Jone', 18, 'test1@baomidou.com'),
3 (2, 'Jack', 20, 'test2@baomidou.com'),
4 (3, 'Tom', 28, 'test3@baomidou.com'),
5 (4, 'Sandy', 21, 'test4@baomidou.com'),
6 (5, 'Billie', 24, 'test5@baomidou.com');

真实开发中,version(乐观锁)、deleted(逻辑删除)、gmt_create、gmt_modified

4.编写项目,初始化项目(新建springboot项目),使用springboot初始化

5.导入依赖

引入spring-boot-starter的父工程

1  <parent>
2         <groupId>org.springframework.boot</groupId>
3         <artifactId>spring-boot-starter-parent</artifactId>
4         <version>2.3.3.RELEASE</version>
5         <relativePath/> <!-- lookup parent from repository -->
6     </parent>
 1 #####数据库驱动#####
 2 <dependency>
 3             <groupId>mysql</groupId>
 4             <artifactId>mysql-connector-java</artifactId>
 5             <scope>runtime</scope>
 6         </dependency>
 7 ###lombok####
 8         <dependency>
 9             <groupId>org.projectlombok</groupId>
10             <artifactId>lombok</artifactId>
11             <optional>true</optional>
12         </dependency>
13 ####mybatis-plus####
14    <dependency>
15             <groupId>com.baomidou</groupId>
16             <artifactId>mybatis-plus-boot-starter</artifactId>
17             <version>3.0.5</version>
18         </dependency>
1   <dependency>
2             <groupId>junit</groupId>
3             <artifactId>junit</artifactId>
4             <scope>test</scope>
5         </dependency>

mybatis-plus可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus,避免版本差异

6.连接数据库  application.properties

1 # mysql 5 驱动不同 com.mysql.jdbc.Driver
2 
3 # mysql 8 驱动不同 com.mysql.cj.jdbc.Driver 需要增加时区的配置
4 #serverTimezone=GMT%2B8
5 spring.datasource.username=root
6 spring.datasource.password=root
7 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

7.使用传统方式的步骤:pojo-dao(连接mybatis,配置mapper.xml文件)-service-controller

7.使用mybatis-plus之后

pojo

1 @Data
2 @NoArgsConstructor
3 @AllArgsConstructor
4 public class User {
5     private Long id;
6     private String name;
7     private Integer age;
8     private String email;
9 }

mapper接口

 1 package com.dz.mybatis_plus.mapper;
 2 
 3 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 4 import com.dz.mybatis_plus.pojo.User;
 5 import org.springframework.stereotype.Repository;
 6 //在对应的Mapper上面继续基本的类    BaseMapper
 7 @Repository//代表持久层
 8 public interface UserMapper extends BaseMapper<User> {
 9     //所有的CRUD操作都已经编写完成了
10     //不需要以前配置一大堆文件
11 }

使用mybatis-plus,mapper接口需要继承BaseMapper,所有的方法都继承基本的类

主启动类扫描mapper包下所有的接口

@MapperScan(mapper文件夹-->包名)

 1 @SpringBootApplication
 2 //我们需要在启动类上去扫描我们的mapper包下的所有接口
 3 @MapperScan("com.dz.mybatis_plus.mapper")
 4 public class MybatisPlusApplication {
 5 
 6     public static void main(String[] args) {
 7         SpringApplication.run(MybatisPlusApplication.class, args);
 8     }
 9 
10 }

测试类中测试

 1 @SpringBootTest
 2 class MybatisPlusApplicationTests {
 3     //继承了BaseMapper所有的方法都来自自己的父类
 4     //我们也可以编写自己的扩展方法
 5     @Autowired
 6     private UserMapper userMapper;
 7 
 8     @Test
 9     void contextLoads() {
10         //参数是一个wrapper,条件构造器,这里我们先不用(null)
11         //查看全部用户
12         List<User> users = userMapper.selectList(null);
13         users.forEach(System.out::println);
14     }
15 
16 }

结果

思考:

  1. 对象与表如何关联?通过注解实现对象与表映射
  2. 如何将CRUD操作做到统一定义?将CRUD操作统一封装到Mapper接口,其他的Mapper只需要集成即可
  3. 数据库只能识别sql语句,如何将对象与sql转化?将对象的操作动态的转化为sql语句,之后交给Mybatis执行

5.配置日志

我们所有的sql现在是不可见的,我们希望知道它是怎么执行的,所以我们必须要看日志

1 #配置日志
2 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

 配置完毕日志之后,后面的学习就需要注意这个自动生成的SQL,你们就会喜欢上MyBatis-Plus

6.CRUD扩展

插入操作

Insert插入

 1 //测试插入
 2     @Test
 3     public void testInsert() {
 4         User user = new User();
 5         user.setName("dz");
 6         user.setAge(22);
 7         user.setEmail("94214242@qq.com");
 8         int result = userMapper.insert(user);//帮我们自动生成id
 9         System.out.println(result);//受影响的行数
10         System.out.println(user);//发现id会自动回填
11     }

 

 

 

 数据库插入的id默认值为:全局的唯一id

7.主键生成策略

待补充.....

8.更新操作

 1     //测试更新
 2     @Test
 3     public void testUpdate(){
 4         User user = new User();
 5         user.setId(1L);
 6         user.setName("dz1");
 7         user.setAge(12);
 8         int i = userMapper.updateById(user);
 9         System.out.println(i);
10     }

 

 

 

 所有的sql都是自动帮你动态配置的。

9.自动填充

创建时间、修改时间、这些操作都是自动化完成的,我们不希望手动更新

阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上,而且需要自动化

方式一:数据库级别(工作中不允许你修改数据库)

1.在表中新增字段create_time、update_time

 

 

2.再次测试插入方法,我们需要先把实体类同步

1     private Date createTime;
2     private Date updateTime;

 

3.再次更新查看结果即可

方式二:代码级别

1.删除数据库的默认值、更新操作

2.实体类字段属性上需要增加注解

1     //字段添加填充内容
2     @TableField(fill = FieldFill.INSERT)
3     private Date createTime;
4     @TableField(fill = FieldFill.INSERT_UPDATE)
5     private Date updateTime;

 

3.编写处理器来处理这个注解即可  handler文件夹中的MyMetaObjectHandler    handler文件夹与pojo文件夹同级

 1 @Slf4j
 2 @Component//一定不要忘记将处理器添加到IOC容器中
 3 public class MyMetaObjectHandler implements MetaObjectHandler {
 4     @Override
 5     public void insertFill(MetaObject metaObject) {
 6         log.info("start insert fill......");
 7         // setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
 8         this.setFieldValByName("createTime",new Date(),metaObject);
 9         this.setFieldValByName("updateTime",new Date(),metaObject);
10     }
11 
12     @Override
13     public void updateFill(MetaObject metaObject) {
14         log.info("start update fill......");
15         this.setFieldValByName("updateTime",new Date(),metaObject);
16     }
17 }

 

4.测试插入

5.测试更新,观察时间即可

 

 

10.乐观锁

在面试过程中,我们经常会被问到乐观锁,悲观锁。

乐观锁:顾名思义十分乐观,它总认为不会出现问题,无论干什么都不去上锁,如果出现了问题,再次更新值测试。

悲观锁:顾名思义十分悲观,它总认为总是会出现问题,无论干什么都会上锁,再去操作。

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

待补充......

测试一下Mybatis-plus的乐观锁插件

1.给数据库中添加version字段

2.实体类添加对应的字段

1 @Version//乐观锁Version注解
2     private Integer version;

 

3.

待补充.....

11.分页查询

分页的实现方式很多

  1. 原始的limit进行分页
  2. pageHelper第三方插件
  3. MP内置了分页插件

如何使用MP

1.配置拦截器组件即可     分页插件PaginationInterceptor在3.4.0之后已被弃用

1  //分页插件
2     @Bean
3     public PaginationInterceptor paginationInterceptor(){
4         return new PaginationInterceptor();
5     }

 

2.直接使用Page对象即可

 1     //测试分页查询
 2     @Test
 3     public void testPage(){
 4         //1.参数1:当前页
 5         //2.参数2:页面大小
 6         //使用了分页插件之后,所有的分页操作也变得简单的
 7         Page<User> page = new Page<>(1,5);
 8         userMapper.selectPage(page,null);
 9         page.getRecords().forEach(System.out::println);
10         System.out.println(page.getTotal());
11     }

 

12.删除操作

1.根据id删除记录

 1     //删除测试
 2     @Test
 3     public void testDeleteById(){
 4         userMapper.deleteById(1299203741953536002L);
 5     }
 6     //通过id批量删除
 7     public void testDeleteBatchId(){
 8         userMapper.deleteBatchIds(Arrays.asList(1299171200475291650L,1299181188920848385L));
 9     }
10     //通过map删除
11     @Test
12     public void testDeleteMap(){
13         HashMap<String,Object> map = new HashMap<>();
14         map.put("name","dz");
15         userMapper.deleteByMap(map);
16     }

 

我们在工作中会遇到一些问题:逻辑的删除

13.逻辑删除

物理删除:从数据库中直接移除

逻辑删除:在数据库中没有被移除,而是通过一个变量来让他失效。例如:deleted=0  --->   deleted=1

管理员可以查看被删除的记录,放置数据的丢失,类似于回收站。

测试:

1.在数据表中增加一个deleted字段

2.在实体类中增加属性

1  @TableLogic //逻辑删除
2     private Integer deleted;

 

3.配置

1 #配置逻辑删除
2 mybatis-plus.global-config.db-config.logic-delete-value=1
3 mybatis-plus.global-config.db-config.logic-not-delete-value=0

 

4.测试一下删除

1 //删除测试
2     @Test
3     public void testDeleteById(){
4         userMapper.deleteById(1L);
5     }
6     //通过id删除
7     public void testDeleteBatchId(){
8         userMapper.deleteBatchIds(Arrays.asList(1299171200475291650L,1299181188920848385L));
9     }

 

 

 

 走的是更新,并不是删除操作

记录依旧在数据库,但是只确已经改变

 

 

 5.查询操作

 

 

 查询操作的时候回自动过滤被逻辑删除的字段

以上的所有CRUD操作及其扩展操作,我们都必须精通掌握,会大大提高自己的工作和写项目的效率。

14.性能分析插件

我们在平时开发中,会遇到一些慢sql。。。。。

作用:性能分析拦截器,用于输入每条SQL语句及其执行时间。

MP也提供性能分析插件,如果超过这个时间就停止运行。

待补充.......

15.条件构造器

Wrapper

我们写一些复杂的sql就可以使用它来替代。

1.测试:记住查看输出的SQL进行分析

 1     @Test
 2     void contextLoads() {
 3         //查询name不为空的用户,并且邮箱不为空的用户,年龄大于等于24
 4         QueryWrapper<User> wrapper = new QueryWrapper<>();
 5         wrapper.isNotNull("name")
 6                 .isNotNull("email")
 7                 .ge("age",24);
 8         //查看全部用户
 9         List<User> users = userMapper.selectList(wrapper);
10         users.forEach(System.out::println);
11     }

 

2.测试:记住查看输出的SQL进行分析

1    @Test
2     void test2(){
3         QueryWrapper<User> queryWrapper = new QueryWrapper<>();
4         queryWrapper.eq("name","dz");
5         //查询一个数据,出现多个结果使用List或者Map
6         User user = userMapper.selectOne(queryWrapper);
7         System.out.println(user);
8     }

 

 

3.测试:记住查看输出的SQL进行分析

1  @Test
2     void test3(){
3         QueryWrapper<User> queryWrapper = new QueryWrapper<>();
4         queryWrapper.between("age",20,30);//区间
5         Integer count = userMapper.selectCount(queryWrapper);
6         System.out.println(count);
7     }

 

 

 

121212

posted @ 2020-08-27 22:25  罗晓峥  阅读(461)  评论(0编辑  收藏  举报