Mybatis-plus 上

简介

1.什么是Mybatis-plus

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

官网:https://baomidou.com/

愿景

我们的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的 1P、2P,基友搭配,效率翻倍。

2.特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

快速入门

我们将通过一个简单的 Demo 来阐述 MyBatis-Plus 的强大功能,在此之前,我们假设您已经:

  • 拥有 Java 开发环境以及相应 IDE
  • 熟悉 Spring Boot
  • 熟悉 Maven

1.数据库

创建一个mybatis-plus数据库

现有一张 User 表,其表结构如下:

id name age email
1 小张 18 test1@qq.com
2 小王 20 test2@163.com
3 小李 25 test3@qq.com
4 小驰 21 test4@qq.com
5 小刘 24 test5@163.com
  • 对应的数据库 Schema 脚本如下:
  1. DROP TABLE IF EXISTS user;
  2. CREATE TABLE user
  3. (
  4. id BIGINT(20) NOT NULL COMMENT '主键ID',
  5. name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
  6. age INT(11) NULL DEFAULT NULL COMMENT '年龄',
  7. email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
  8. PRIMARY KEY (id)
  9. );

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

  • 其对应的数据库 Data 脚本如下:
  1. DELETE FROM user;
  2. INSERT INTO user (id, name, age, email) VALUES
  3. (1, '小张', 18, 'test1@qq.com'),
  4. (2, '小王', 20, 'test2@163.com'),
  5. (3, '小李', 25, 'test3@qq.com'),
  6. (4, '小驰', 21, 'test4@qq.com'),
  7. (5, '小刘', 24, 'test5@163.com');

2.初始化工程

创建一个SpringBoot项目:创建时选择 starter-web 依赖。

2.1 导入依赖

  1. <!-- 数据库驱动 -->
  2. <dependency>
  3. <groupId>mysql</groupId>
  4. <artifactId>mysql-connector-java</artifactId>
  5. </dependency>
  6. <!-- lombok -->
  7. <dependency>
  8. <groupId>org.projectlombok</groupId>
  9. <artifactId>lombok</artifactId>
  10. </dependency>
  11. <!-- mybatis-plus -->
  12. <dependency>
  13. <groupId>com.baomidou</groupId>
  14. <artifactId>mybatis-plus-boot-starter</artifactId>
  15. <version>3.1.0</version>
  16. </dependency>

使用mybatis-plus可以节省我们大量的代码,尽量不要同时导入 mybatismybatis-plus

2.2 连接数据库

直接在application.properties配置文件中配置:

  1. # mysql 5 驱动不同
  2. # mysql 8 驱动不同、需要增加时区 serverTime=UTC
  3. spring.datasource.username=root
  4. spring.datasource.password=148729
  5. spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false&useUnicode=true&charEncoding=utf-8&serverTime=UTC
  6. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3.搭建项目

传统方式:pojo---dao(连接mybatis,配置mapper.xml文件)--- service---- controller

使用了mybatis-plus:

  • pojo
  • mapper接口
  • 启动

3.1 pojo

这里使用了lombok插件,导入lombok依赖,

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

3.2 mapper

  • 创建一个xxxmapper接口
  • 该接口继承BaseMapper<>,泛型为实体类
  • 加注解@Repository
  1. @Repository
  2. public interface UserMapper extends BaseMapper<User> {
  3. }

3.3 启动器

加入@MapperScan(""),对mapper包进行扫描

  1. @SpringBootApplication
  2. @MapperScan("com.zc.mapper")
  3. public class MybatisPlus01QsApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(MybatisPlus01QsApplication.class, args);
  6. }
  7. }

3.4 测试类

  1. @SpringBootTest
  2. class MybatisPlus01QsApplicationTests {
  3. @Autowired
  4. private UserMapper userMapper;
  5. @Test
  6. void contextLoads() {
  7. //查询全部用户
  8. List<User> users = userMapper.selectList(null);
  9. users.forEach(System.out::print;
  10. }
  11. }

4.配置日志

在配置文件中进行配置:

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

测试运行:

插入操作

1.插入数据

  1. @Test
  2. void insert() {
  3. //插入新用户
  4. User user = new User();
  5. user.setName("咚咚");
  6. user.setAge(16);
  7. user.setEmail("111@insert.com");
  8. int insert = userMapper.insert(user);
  9. System.out.println(insert);
  10. System.out.println(user);
  11. }

我们从上图可以看出:主键自动生成

2.雪花算法

2.1 含义

SnowFlake算法是Twitter公司出品的开源的分布式id生成算法,结果是一个long型的ID

其特点为 使用一个64 bit的long型的数字作为全局唯一 id

雪花算法在分布式系统中的应用十分广泛 且引入了时间戳 基本保持自增

2.2 字符串含义

其核心思想是:

41bit作为毫秒数

10bit作为机器的ID(5个bit是数据中心,5个bit的机器D)

12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID)

最后还有个符号位,永远是0。可以保证几乎全球唯一!

  • 第1位是符号位 始终为0

    (这是因为生成的id都是正数 而在二进制中第一个bit若为0则不为负数)

  • 后面是41位的时间戳 精确到毫秒级

    41位的长度可以表示2^41-1个毫秒值 也就是说可以使用69年

    时间戳还有一个很重要的作用 可以根据时间进行排序

  • 之后的10位是机器标识 前5bit是机房id 后5bit是机器id

    10位的长度表明该服务最多可以部署在2^10台机器(即1024台机器)上

  • 最后12位是计数序列号

    序列号是一系列的自增id 表示了同一个毫秒内产生的不同id

    可以支持同一节点同一毫秒生成多个id 12位的计数序列号支持每个节点每毫秒产生2^12-1(即4096)个ID序号

2.3 生成过程

  1. 若某个服务需要生成一个唯一id 则发送一个请求给部署了SnowFlake算法的系统(前提是该SnowFlake算法系统知道自己所在的机房和机器的编号)

  2. SnowFlake算法系统接收到该请求后 使用二进制位运算的方式生成一个64bit的long型id 当然 第一个bit是无意义的

  3. 接着41个bit使用当前时间戳(单位为毫秒) 然后的5bit设为该机房的id 剩余5bit设为机器的id

  4. 最后 再判断当前机房的该机器在这一毫秒内是第几个请求 给本次生成id的请求后再累加一个序号 作为id最后的12个bit

至此 就得到了一个64bit的唯一id 这就是雪花算法

3.主键自增

需要配置主键自增:

  1. 开启数据库 主键自增

  2. 实体类主键字段上 @TableId(type=IdType.AUTO)

  3. 再次测试

IdType类中枚举解释

  1. AUTO(0), // 数据库id自增
  2. NONE(1), // 未设置主键
  3. INPUT(2), // 手动输入
  4. ID_WORKER(3), // 默认的全局唯一id
  5. UUID(4), // 全局唯-id uuid
  6. ID_WORKER_STR(5); // ID_WORKER 字符串表示法

更新操作

  1. @Test
  2. void update() {
  3. //更新用户
  4. User user = new User();
  5. user.setId(5L); // id 在数据库中设置的类型为 long
  6. user.setName("我不是小刘啦");
  7. // 虽然是ById,实际上应该传入 泛型T
  8. int i = userMapper.updateById(user);
  9. }

mybatis-plus 中都是自动化,自动拼接动态Sql

自动填充

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

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

1.数据库级别

如果你使用的Navicat Premium,在mysql5.5以上已经不支持两个字段自动更新

如果觉得很麻烦,可以直接看第二种代码级别自动填充

1、在表中新增字段create_timeupdate_time

因为不支持两个列为timestamp类型,所以这里设置更新时间为timestamp

下面的默认必须为CURRENT_TIMESTAMP,然后打对号

如果没有CURRENT_TIMESTAMP,可以使用两个方法:

一、默认框下拉,选择空白处,将这段英文复制进去 ,然后保存

二、把表删了,运行下面的sql语句

  1. CREATE TABLE `mybatis-plus`.`Untitled` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  3. `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名',
  4. `age` int(11) NULL DEFAULT NULL COMMENT '年龄',
  5. `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
  6. `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  7. `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  8. PRIMARY KEY (`id`) USING BTREE
  9. ) ENGINE = InnoDB AUTO_INCREMENT = 1374350451559940100 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT;

2.实体类增加字段

  1. private Date createTime;
  2. private Date updateTime;

3.更新测试

数据库中的更新时间也会进行更新

2.代码级别

1.在表中新增字段create_timeupdate_time

2.实体类加入注解

  1. @TableField(fill = FieldFill.INSERT)
  2. private Date createTime;
  3. @TableField(fill = FieldFill.INSERT_UPDATE)
  4. private Date updateTime;

3.创建配置类

  1. @Component
  2. @Slf4j
  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. @Override
  12. public void updateFill(MetaObject metaObject) {
  13. log. info("start update fill.....");
  14. this.setFieldValByName ("updateTime", new Date(), metaObject);
  15. }
  16. }

4.插入测试

  1. @Test
  2. void insert() {
  3. User user = new User();
  4. user.setName("邦邦");
  5. user.setAge(20);
  6. user.setEmail("insert@insert.com");
  7. int insert = userMapper.insert(user);
  8. System.out.println(insert);
  9. System.out.println(user);
  10. }

5.更新测试

  1. @Test
  2. void update() {
  3. User user = new User();
  4. user.setId(5L); // id 在数据库中设置的类型为 long
  5. user.setName("我bu是小刘啦");
  6. // 虽然是ById,实际上应该传入 泛型T
  7. int i = userMapper.updateById(user);
  8. }

乐观锁

乐观锁:故名思意十分乐观,总是认为不会出现问题,无论干什么不去上锁,先进行事务,如果出现了问题,再次更新值测试

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

乐观锁实现方式:

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

举例:

  1. 先查询出 version,进行操作时 version + 1
  2. 线程A
  3. update user set name = "zc",version = version+1 where id=? and version=1
  4. 线程B
  5. update user set name = "zc",version = version+1 where id=? and version=1

可以看出,先查询了老的version,在更新时version+1;

如果 线程B先于线程A完成该更新操作,那version==2,这时候线程A不成立,更新失败

添加乐观锁

1.数据库中添加version字段:int类型,全部设为 1 即可

2.实体类加入对应字段、注释

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

3.注册组件

  1. @EnableTransactionManagement
  2. @Configuration
  3. @MapperScan("com.zc.mapper")
  4. public class MyBatisPlusConfig {
  5. //注册乐观锁插件
  6. @Bean
  7. public OptimisticLockerInterceptor optimisticLockerInterceptor() {
  8. return new OptimisticLockerInterceptor();
  9. }
  10. }

4.测试乐观锁

成功:

  1. @Test
  2. public void optimisticlocker_success(){
  3. //1、查询用户信息
  4. User user = userMapper.selectById(1L);
  5. //2、修改用户信息
  6. user.setName("zc");
  7. user.setEmail("update@qq.com");
  8. //3、执行更新操作
  9. userMapper.updateById(user);
  10. }

失败:

  1. @Test
  2. public void optimisticlocker_fail(){
  3. //线程A
  4. User user = userMapper.selectById(1L);
  5. user.setName("zc");
  6. user.setEmail("A@qq.com");
  7. //线程B
  8. User user1 = userMapper.selectById(1L);
  9. user.setName("zc1");
  10. user.setEmail("B@qq.com");
  11. userMapper.updateById(user1);
  12. userMapper.updateById(user);
  13. }

我们使,线程B 先于 线程A 进行更新。

这时会发现,虽然可以运行,version字段也会增加,但是并不会进行更新。

个人博客为:

MoYu's HomePage

MoYu's Gitee Blog

Mybatis-plus 上的更多相关文章

  1. 带着新人学springboot的应用01(springboot+mybatis+缓存 上)

    上一篇结束,第一次做一个这么长的系列,很多东西我也是没有说到,也许是还没有想到,哈哈哈,不过基本的东西还是说的差不多了的.假如以后碰到了不会的,随便查查资料配置一下就ok. 咳,还有大家如果把我前面的 ...

  2. Spring与MyBatis整合上_Mapper动态代理方式

         将MyBatis与Spring进行整合,主要解决的问题就是将SqlSessionFactory对象交由Spring来管理..所以该整合,只需将SQLSessionFactory的对象生成器S ...

  3. myBatis + SpringMVC上传、下载文件

    摘自: http://limingnihao.iteye.com/blog/1069503 环境:maven+SpringMVC + Spring + MyBatis + MySql 本文主要说明如何 ...

  4. SpringMVC , Spring , MyBatis 文件上传

    学习一下文件上传下载,为图片上传做准备,感觉有一个世纪没玩过上传下载了,边敲代码边记录,请各路大神指教: 参考:http://blog.csdn.net/wjycgl/article/details/ ...

  5. Mybatis(上)

    Mybatis 一.MyBatis 简介 1. MyBatis作用 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架. MyBatis 避免了几乎所有的 JDBC 代码和手 ...

  6. 【SpringBoot】11.Springboot整合SpringMVC+Mybatis(上)

    Springboot整合SpringMVC+Mybatis 需求分析:通过使用Springboot+SpringMVC+Mybatis 整合实现一个对数据库表users表的CRUD操作. 1.创建项目 ...

  7. MyBatis史上最全文章

    老规矩,本篇文章 不做 MyBatis 的 编码讲解 ,只介绍 文章学习的一些优秀文章 重点在于不要循规蹈矩,教程 这样走,你不一定要按他这样走,按自己的方式来,学习效率会更高,网上的教程有很多,今天 ...

  8. MyBatis从入门到精通(第9章):Spring集成MyBatis(上)

    MyBatis从入门到精通(第9章):Spring集成MyBatis(上) Spring是一个为了解决企业级Web应用开发过程中面临的复杂性,而被创建的一个非常流行的轻量级框架. mybatis-sp ...

  9. mybatis - resultMap

    resultMap有比较强大的自动映射,下面是摘自mybatis中文官网的的片段: 当自动映射查询结果时,MyBatis会获取sql返回的列名并在java类中查找相同名字的属性(忽略大小写). 这意味 ...

  10. Spring学习笔记--spring+mybatis集成

    前言: 技术的发展, 真的是日新月异. 作为javaer, 都不约而同地抛弃裸写jdbc代码, 而用各种持久化框架. 从hibernate, Spring的JDBCTemplate, 到ibatis, ...

随机推荐

  1. 2020 新型肺炎病毒疫情 & 远程办公

    2020 新型肺炎病毒疫情 & 远程办公 2020 新型肺炎病毒疫情 https://zhuanlan.zhihu.com/p/104406687 钉钉 微信 code gitlab PRD ...

  2. HGAME apache

    HGAME apache Linux下六十四位可执行文件 IDA找主函数 输入长度为35的字符串,经过一次函数处理,之后if条件函数的返回值为1,就能判定输入就是flag 函数sub_1447的参数 ...

  3. 教你玩转CSS 居中

    1.元素居中对齐 要水平居中对齐一个元素(如 <div>), 可以使用 margin: auto;. 设置到元素的宽度将防止它溢出到容器的边缘. 元素通过指定宽度,并将两边的空外边距平均分 ...

  4. 2. Vue语法--插值操作&动态绑定属性 详解

    目录 1. 设置vue模板 2. vue语法--插值操作 3. 动态绑定属性--v-bind 一. 设置vue模板 我们经常新建一个vue项目的时候, 会写如下的一段代码 <!DOCTYPE h ...

  5. Excel和CSV格式文件的不同之处

    来源:https://blog.csdn.net/weixin_39198406/article/details/78705016 1.个人理解:为何选择使用csv来存储接口测试用例相关字段数据,而不 ...

  6. NDK android Error:Expected caller to ensure valid ABI: MIPS

    android studio 安装NDK之后,报错 Error:Expected caller to ensure valid ABI: MIPS 环境: android studio 2.3 gra ...

  7. Python3+PYQT5 实现并打包exe小工具(1)

    前言: 由于项目原因,配置测试环境与正式环境切换频率很高,固写了一键切换环境的工具.用于记录. 实现逻辑: 1.读取注册表中客户端的安装目录,把固定的环境配置文件添加到固定目录下实现配置测试环境: 2 ...

  8. 使用Maven新建SpringBoot工程

    最近用IDEA插件创建Springboot项目,总是403,估计被墙了! 那么这里在提供两种方法 1.从官网下载模板,导入IDEA内 2.使用Maven创建 方法一:打开 https://start. ...

  9. STL容器整理

    1.vector c++STL中的可变长度数组,主要支持操作有:建立,添加到末尾,返回长度,调整大小,定义迭代器及对迭代器的具体操作.具体如下: 1.建立一个元素类型为int的可变长度数组v,最开始N ...

  10. Python3+pygame实现的俄罗斯方块 代码完整 有演示效果

    一.简单说明 80.90后的小伙伴都玩过"俄罗斯方块",那种"叱咤风云"场景 偶尔闪现在脑海 真的是太爽了:如果没有来得及玩过的同学,这次可以真正的自己做一个了 ...