Mybatis-plus一谈到底(简介、快速入门、MyBatisPlus的CRUD 接口、MyBatisPlus条件构造器)

    技术2022-07-29  82

    思维导图原图下载,也可以私聊给我留言,看到就会回复

    本人是一名物联网工程专业的学生,写博客即是为了记录自己的学习历程,又希望能够帮助到很多和自己一样处于起步阶段的萌新。 临渊羡鱼,不如退而结网。一起加油! 博客主页:https://blog.csdn.net/qq_44895397

    MyBatisPlus简介

    一、简介

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

    二、特性

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

    MyBatisPlus入门

    一、使用 Spring Initializr 快速初始化一个 Spring Boot 工程

    二、添加依赖

    mybatis-plus-boot-starter、MySQL依赖:

    <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>

    三、配置

    在 application.properties 配置文件中添加 MySQL 数据库的相关配置

    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=yky

    四、代码编写

    1、mapper继承BaseMapper接口

    @Mapper public interface StudentMapper extends BaseMapper<tStudent> { }

    2、实体类

    注意数据库表名和实体类名称的关系:

    3、启动类

    五、配置日志

    控制台输出sql语句:

    核心配置文件配置

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

    六、测试

    @SpringBootTest public class Mybatisplusdemo01ApplicationTests { @Autowired private StudentMapper studentMapper; @Test void contextLoads() { List<tStudent> students = studentMapper.selectList(null); for (tStudent s : students) { System.out.println(s); } } }

    MyBatisPlus的CRUD 接口

    一、insert

    1、插入操作

    直接调用BaseMapper接口中的方法即可

    //插入操作 @Test public void add(){ tStudent student = new tStudent(); student.setName("爱敲代码的小游子"); student.setAge(19); studentMapper.insert(student); }

    2、主键策略

    (1)ID_WORKER

    MyBatis-Plus默认的主键策略是:ID_WORKER 全局唯一ID

    (2)自增策略
    要想主键自增需要配置如下主键策略 需要在创建数据表的时候设置主键自增实体字段中配置 @TableId(type = IdType.AUTO) @TableId(type = IdType.AUTO) private Integer id; 要想影响所有实体的配置,可以设置全局主键配置 #全局设置主键生成策略 mybatis-plus.global-config.db-config.id-type=auto 其它主键策略:

    二、update

    1、根据Id更新操作

    @Test public void updateStudent() { tStudent student = new tStudent(); student.setId(1009); student.setName("东方不败"); studentMapper.updateById(student); }

    2、自动填充

    (1)数据库表中添加自动填充字段

    (2)实体上添加注解
    //自动填充 @TableField(fill = FieldFill.INSERT) private Date create_time; @TableField(fill = FieldFill.INSERT_UPDATE) private Date update_time;

    (3)实现元对象处理器接口

    注意:不要忘记添加 @Component 注解

    @Component public class MyMateObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.setFieldValByName("update_time",new Date(),metaObject); this.setFieldValByName("create_time",new Date(),metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("update_time",new Date(),metaObject); } }
    注意事项
    字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus需要预留注入SQL字段填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component或@Bean注入要想根据注解FieldFill.xxx和字段名以及字段类型来区分必须使用父类的strictInsertFill或者strictUpdateFill方法不需要根据任何来区分可以使用父类的fillStrategy方法

    3、乐观锁

    主要解决:丢失更新,也就是说实现线程安全的数据更新

    1、乐观锁实现方式:
    取出记录时,获取当前version更新时,带上这个version执行更新时, set version = newVersion where version = oldVersion如果version不对,就更新失败
    2、配置步骤:
    插件配置 /** * 乐观锁插件 */ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } 在实体类中的version属性添加@Version注解 //乐观锁 @TableField(fill = FieldFill.INSERT) @Version private Integer version;
    3、特别说明
    支持的数据类型只有 int,Integer,long,Long,Date,Timestamp,LocalDateTime整数类型下 newVersion = oldVersion + 1newVersion 会回写到 entity 中仅支持 updateById(id) 与 update(entity, wrapper) 方法在 update(entity, wrapper) 方法下, wrapper 不能复用!!!

    三、select

    1、根据id查询记录

    @Test void selecttStudentById() { tStudent students = studentMapper.selectById(1004); System.out.println(students); }

    2、通过多个id批量查询

    @Test void selecttStudentById() { List<tStudent> tStudents = studentMapper.selectBatchIds(Arrays.asList(1001, 1002, 1003)); System.out.println(tStudents ); }

    3、简单的条件查询

    通过map封装查询条件

    注意:map中的key对应的是数据库中的列名。 @Test public void testSelectByMap(){ HashMap<String, Object> map = new HashMap<>(); map.put("name", "爱敲代码的小游子"); map.put("age", 19); List<User> users = userMapper.selectByMap(map); users.forEach(System.out::println); }

    4、分页查询

    MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

    配置类中添加分页插件
    @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false // paginationInterceptor.setOverflow(false); // 设置最大单页限制数量,默认 500 条,-1 不受限制 // paginationInterceptor.setLimit(500); // 开启 count 的 join 优化,只针对部分 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; }
    分页插件的使用
    1、创建page对象
    //创建page对象 //两个参数:当前页和每页显示记录数 Page<tStudent> studentPage = new Page<>(1,3);
    2、通过调用分页查询的方法

    @Test public void pageHander(){ //创建page对象 //两个参数:当前页和每页显示记录数 Page<tStudent> studentPage = new Page<>(1,3); //调用分页查询方法 //分页查询过程中,把分页所有的数据封装到page对象里面 studentMapper.selectPage(studentPage,null); studentPage.getCurrent();//当前页 studentPage.getRecords();//每页数据的list集合 studentPage.getSize();//每页显示记录数 studentPage.getTotal();//总记录数 studentPage.getPages();//总页数 System.out.println(studentPage.getPages()); studentPage.hasNext();//判断是否还有下一页 studentPage.hasPrevious();//判断是否还有上一页 }

    四、delete

    1、根据id删除记录

    @Test public void testDeleteById(){ int result = userMapper.deleteById(8L); System.out.println(result); }

    2、批量删除

    @Test public void testDeleteBatchIds() { int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10)); System.out.println(result); }

    3、简单的条件查询删除

    @Test public void testDeleteByMap() { HashMap<String, Object> map = new HashMap<>(); map.put("name", "Helen"); map.put("age", 18); int result = userMapper.deleteByMap(map); System.out.println(result); }

    4、逻辑删除

    物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
    (1)数据库中添加 deleted字段

    (2)实体类属性deleted 添加注解@TableLogic
    @TableLogic @TableField(fill = FieldFill.INSERT) private Integer deleted;
    (3)新增数据时自动填充deleted默认值

    在数据库中增加deleted字段时设置默认值后不需要再在这里设置默认值

    this.setFieldValByName("deleted",0,metaObject);
    (4)application.properties 加入配置(可不配置)
    ##逻辑删除配置 #mybatis-plus.global-config.db-config.logic-delete-value=1 #mybatis-plus.global-config.db-config.logic-not-delete-value=0

    MyBatisPlus条件构造器

    了解更多可以参考官方文档:https://mp.baomidou.com/

    创建QueryWrapper对象

    QueryWrapper<tStudent> wrapper = new QueryWrapper<>();

    1、ge、gt、le、lt、isNull、isNotNull

    ge:大于等于 >=gt:大于 >le:小于等于 <=lt:小于 <isNull:字段 IS NULLisNotNull:字段 IS NOT NULL public void text(){ QueryWrapper<tStudent> wrapper = new QueryWrapper<>(); wrapper.ge("id",1004); wrapper.le("age",50); List<tStudent> tStudents = studentMapper.selectList(wrapper); System.out.println(tStudents); }

    2、eq、ne

    eq:等于ne:不等于 eq("name", "老王")--->name = '老王'

    3、between、notBetween

    包含大小边界

    BETWEEN 值1 AND 值2 between("age", 18, 30)--->age between 18 and 30

    4、allEq

    allEq(Map<R, V> params) allEq(Map<R, V> params, boolean null2IsNull) allEq(boolean condition, Map<R, V> params, boolean null2IsNull) 例1: allEq({id:1,name:"老王",age:null})—>id = 1 and name = '老王' and age is null例2: allEq({id:1,name:"老王",age:null}, false)—> id = 1 and name = '老王'

    5、last

    无视优化规则直接拼接到 sql 的最后

    注意事项:

    只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用 //复杂条件查询 @Test public void select(){ QueryWrapper<tStudent> wrapper = new QueryWrapper<>(); wrapper.last("and name = ''"); List<tStudent> tStudents = studentMapper.selectList(wrapper); System.out.println(tStudents); }
    Processed: 0.009, SQL: 9