我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MyBatisPlus总结

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MyBatisPlus总结

目录

MyBatisPlus

MP特点

MP框架结构

MP使用准备

导入依赖

springboot整合mybatisplus配置文件

定义好实体类User后编辑mapper接口

@Mapper与@MapperScan("包名")区别

MP基本操作

新增操作

删除操作

通过id删除用户

通过map作为条件删除

通过多个id实现删除

更新用户

通过id进行用户更新

查询用户 

根据id查询用户

根据多个id查询用户

根据map集合作为条件查询用户

通用Service接口

一些操作 

查询总记录数

批量添加数据

MP常用注解

雪花算法

前言

垂直分表

水平分表

条件构造器

继承结构

使用条件构造器实现查询操作

查询所有用户

根据构造器查询主键字段集合

根据条件构造器查询多用户

关于模糊查询

 in查询

转义字符方式查询并排序

条件构造器实现删除操作

使用条件构造器实现修改操作

条件的优先级

组装select语句

组装子查询

动态sql查询

使用updateWrapper实现修改功能

LambdaQueryWrapper

LambdaUpdateWrapper

MP的分页插件

配置配置类(必然)

MP实现分页 

自定义分页功能

MP乐观锁

在需要改变的实体类中加version注解

添加乐观锁插件 

测试 

通用枚举

MP自动填充功能

添加配置类

为实体类添加注解 

测试 

MyBatisPlus

含义:mybatis-plus是个mybatis的增强工具,在mybatis的基础上只做增强不做改变,为简化开发,提高效率而生

注意:我们可以直接在mybatis的基础上直接去集成mybatisplus,这样并不会影响mybatis的功能,同时我们也可以使用他所提供的功能。

MP特点

  • 对mybatis只做增强不做改变,引入他不会对现有工程产生影响
  • 只需要简单的配置即可快速进行单表CRUD操作,从而节省大量的时间
  • 代码生成,自动分页,逻辑删除,自动填充功能等一应俱全

MP框架结构

理解:

  • MP由MP启动器、注解部分、扩展部分、core核心部分、代码生成部分所组成;由这些内容共同支持了MP去实现功能的过程
  • MP实现功能:首先,扫描实体类,扫描之后通过反射技术将实例类中的属性进行抽取,抽取之后来分析表和实体类之间的关系;以及通过反射所抽取出来的实体类中的属性与我们当前字段之间的关系;再根据我们当前调用的方法来生成相对应的sql语句,然后再把增删改查的sql语句注入到mybatis的容器中从而实现最终的功能

MP使用准备

导入依赖

                            org.springframework.boot            spring-boot-starter                                    org.springframework.boot            spring-boot-starter-test            test                                    org.projectlombok            lombok            true                                    com.baomidou            mybatis-plus-boot-starter            3.5.1                                    mysql            mysql-connector-java            runtime            

springboot整合mybatisplus配置文件

spring:  #设置数据源信息  datasource:    #配置数据源类型    type: com.zaxxer.hikari.HikariDataSource    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql:///mybatis_plus?characterEncoding=utf-8&userSSL=false&serverTimezone=GMT%2B8    username: root    password: rootmybatis-plus:  configuration:    #MP提供了日志功能    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl    #驼峰映射(默认就是开启的)    map-underscore-to-camel-case: true  #设置MP的全局配置  global-config:    db-config:      #这样设置的话,那么实体类所有的表都会加上t_前缀      table-prefix: t_      #设置统一主键生成策略      id-type: auto  #映射文件路径  mapper-locations: classpath:/mapper/UserMapper.xml  #配置类型别名所对应的包  type-aliases-package: cn.tedu.mybatisplus.pojo  #扫描通用枚举的包  type-enums-package: cn.tedu.mybatisplus.enums

定义好实体类User后编辑mapper接口

//使用MP提供的通用mapper——BaseMapper//BaseMapper里的泛型表示实体类的类型@Mapperpublic interface UserMapper  extends BaseMapper {}

注意:

  • MP封装了许多常用的CRUD方法,用户需要的时候只需要继承公共的业务接口BaseMapper即可,进而提高了效率
  • BaseMapper接口必须添加泛型,因为其要根据泛型对象获得指定的注解(并获取其中注解的值)、表名及其其中的属性

@Mapper与@MapperScan("包名")区别

  • @MapperScan("包名"):扫描指定包下的mapper接口,将该接口的代理类交给spring容器来保存
  • @Mapper:将该接口的代理类交给spring容器来保存
  • @Mapper用在指定接口上,@MapperScan("对应接口所在包名")用在启动类或配置文件上 

MP基本操作

注意:使用前注入userMapper 

新增操作

        User user = new User();        user.setName("lili").setAge(23).setEmail("lili@qq.com");        int insert = userMapper.insert(user);        System.out.println(insert);        //mybatis-plus会自动获取id        System.out.println(user.getId());

删除操作

通过id删除用户

        int i = userMapper.deleteById(7);        System.out.println(i);

通过map作为条件删除

        Map map=new HashMap<>();        map.put("name", "张三");        map.put("age", 23);        //删除name为张三,age为23的人        int i = userMapper.deleteByMap(map);        System.out.println(i);

通过多个id实现删除

        List list = Arrays.asList(1L, 2L, 3L);        int i = userMapper.deleteBatchIds(list);        System.out.println(i);

更新用户

通过id进行用户更新

        User user = new User();        user.setId(3L).setName("lan").setEmail("lan@qq.com");        //根据id修改元素        int i = userMapper.updateById(user);        System.out.println(i);

查询用户 

根据id查询用户

        User user = userMapper.selectById(1L);        System.out.println(user);

根据多个id查询用户

        List list = Arrays.asList(1L, 2L, 3L);        List users = userMapper.selectBatchIds(list);        users.forEach(System.out::println);

根据map集合作为条件查询用户

        HashMap map = new HashMap<>();        map.put("name", "lan");        map.put("age", 28);        List users = userMapper.selectByMap(map);        //list会直接打印对象数组        System.out.println(users);

通用Service接口

说明:通用Service封装了IService接口,进一步封装了CRUD采用get查询单行,remove删除,list查询集合,page分页等前缀命名方式,区分Mapper层,避免混淆

//service接口public interface UserService extends IService {}
//service实现类@Servicepublic class UserServiceImpl extends ServiceImpl implements UserService {}

注意:

  • ServiceImpl实现了IService接口
  • 使用时应先注入userService

一些操作 

查询总记录数

        //查询总记录数        long count = userService.count();        System.out.println(count);

批量添加数据

        ArrayList list = new ArrayList<>();        for (int i = 1; i <=10 ; i++) {            User user = new User();            user.setName("cjc"+i).setAge(10+i);            list.add(user);        }        //批量添加数据        boolean b = userService.saveBatch(list);        //操作成功或失败        System.out.println(b);

MP常用注解

//设置实体类所对应的表名,若对象与表名一致,则表名中()可以省略@TableName("t_user")public class User {    //将当前属性对应的字段指定为主键(将该属性与数据库中的id字段进行映射),并通过雪花算法生成主键id    //type标识主键的生成策略为自动递增,要求数据库的主键为自增策略(默认为雪花算法——IdType.ASSIGN.ID)    @TableId(value = "id")    private Long id;    //将该注解标识的属性与数据库中的name字段一一映射,若属性名与字段名相同,则注解可省略    @TableField(value = "name")    private String name;    private Integer age;    private String email;    //逻辑删除0标识未删除,1标识已删除    //被逻辑删除的数据用户查不到,但是可以在数据库中看到,只是该属性变为1;(为修改操作)    @TableLogic    private Integer isDeleted;}

注意:@TableField(exit=false)注解一般用在注入的属性上,被该注解标识表名当前属性不参与MP的操作 

雪花算法

前言

背景:需要合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量

数据库表的扩展方式:业务分库、主从复制、数据库分表

数据库分表的两种方式

  • 垂直分表
  • 水平分表

垂直分表

将重要的数据放到一个表中,不在业务查询中用到的独立到另一个表中,以提升一定的性能

水平分表

主键自增:比如按照范围分表(1-9999放入表一,10000-20000放入表二)

取模:主键%数据库个数,余数相同的放入一个表中

雪花算法:

雪花算法是由Twitter分布式主键生成算法,他保证不同表的主键的不重复性,以及相同表的主键的有序性

核心思想:

  1. 长度为64bit
  2. 首先是符号位,1bit标识,由于long基本类型在java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
  3. 4bit是时间戳(ms级别),存储的是时间戳的差值(当前时间戳-开始时间戳),结果约为69.73年
  4. 10bit作为机器的id(5bit是数据中心,5bit是机器id,可以部署在1024个节点上)
  5. 12bit作为ms内的流水号(意味着每个节点在每毫秒可以产生4096个id)

优点:整体上按照时间自增排序,并且整个分布式系统内不会产生id碰撞

条件构造器

作用:封装当前的条件

继承结构

AbstractWrapper:用于条件查询封装,生成sql的where条件

  1. QueryWrapper:查询条件封装
  2. UpdateWrapper:Update条件封装
  3. AbstractLambdaWrapper:使用lambda语法

AbstractLambdaWrapper

  1. LambdaQueryWrapper:用于lambda语法使用的查询Wrapper
  2. LambdaUpdateWrapper:lambda更新封装Wrapper

使用条件构造器实现查询操作

查询所有用户

        //通过条件构造器查询一个list集合,若没有条件则可以设置null(相当于查询所有)        List users = userMapper.selectList(null);        users.forEach(System.out::println);

根据构造器查询主键字段集合

        //查询name为lei的主键字段        QueryWrapper queryWrapper = new QueryWrapper<>();        queryWrapper.eq("name", "lei");        List list = userMapper.selectObjs(queryWrapper);        System.out.println(list); 

根据条件构造器查询多用户

        //查询用户名包含a,年龄在20-30之间,邮箱信息不为null的用户信息        QueryWrapper queryWrapper = new QueryWrapper<>();        //queryWrapper可以实现链式加载        queryWrapper.like("name", "a").between("age", 20, 30).isNotNull("email");        List users = userMapper.selectList(queryWrapper);        System.out.println(users);
        //对象形式        User user = new User();        user.setAge(28);        QueryWrapper queryWrapper = new QueryWrapper<>(user);        List users = userMapper.selectList(queryWrapper);        System.out.println(users);        //user内的属性最终会以and形式拼接

关于模糊查询

  • like:表示a左右都有%
  • likeleft:表示a左边有%
  • likeright:表示a右边有%

 in查询

        //in查询,查询id为1,2,3的数据        Integer[] ids={1,2,3};        QueryWrapper queryWrapper = new QueryWrapper<>();        queryWrapper.in("id",ids);        List users = userMapper.selectList(queryWrapper);        System.out.println(users);

转义字符方式查询并排序

        //查询id>2的用户,按照年龄降序排序,若年两相同则按照id升序排序        QueryWrapper queryWrapper = new QueryWrapper<>();        queryWrapper.gt("id", 2).orderByDesc("age").orderByAsc("id");        List users = userMapper.selectList(queryWrapper);        System.out.println(users);

转义字符

  • >:gt
  • <:lt
  • =:eq
  • >=:ge
  • <=:le
  • != :ne

条件构造器实现删除操作

        //删除邮箱地址为null的用户信息        QueryWrapper queryWrapper = new QueryWrapper<>();        queryWrapper.isNull("email");        int i = userMapper.delete(queryWrapper);        System.out.println(i);

使用条件构造器实现修改操作

        //将年龄>20并且用户名中包含a或邮箱为null的用户进行修改(默认情况下就是and连接)        //修改条件        QueryWrapper queryWrapper = new QueryWrapper<>();        queryWrapper.gt("age", 20).like("name", "a").or().isNull("email");        User user = new User();        user.setName("lei").setEmail("test@cj.com");        int i = userMapper.update(user, queryWrapper);        System.out.println(i);

条件的优先级

        //将用户名中包含a并且(年龄大于20或邮箱为null)的用户信息进行修改        QueryWrapper queryWrapper = new QueryWrapper<>();        //lambda中的条件优先执行(i就表示条件构造器)        queryWrapper.like("name", "a").and(i-> i.gt("age", 20).or().isNull("email"));        User user = new User();        user.setName("red").setEmail("test@cj.com");        int i = userMapper.update(user, queryWrapper);        System.out.println(i);

组装select语句

        //查询出来一个以map为泛型的list集合        //查询用户名、年龄、邮箱信息        QueryWrapper queryWrapper = new QueryWrapper<>();        queryWrapper.select("name","age","email");        List> maps = userMapper.selectMaps(queryWrapper);        System.out.println(maps);

组装子查询

        //select * from t_user where id in(select id from t_user where id<=100)        //查询id<=100的用户信息        QueryWrapper queryWrapper = new QueryWrapper<>();        queryWrapper.inSql("id", "select id from t_user where id<=100");        List users = userMapper.selectList(queryWrapper);        System.out.println(users);

动态sql查询

        String name=null;        String  age="21";        //判断字符串是否为null或空串若为返回false,不为返回true        boolean pn = StringUtils.hasLength(name);        boolean pa = StringUtils.hasLength(age);        QueryWrapper queryWrapper = new QueryWrapper<>();        //判断属性是否为true,为true则执行该条件,不为则忽略该条件        queryWrapper.eq(pn,"name",name).eq(pa, "age", age);        List users = userMapper.selectList(queryWrapper);        System.out.println(users);

注意:queryWrapper.clear();为清除多余的条件,清除后queryWrapper可以继续使用 

使用updateWrapper实现修改功能

        //查询用户名中包含a(年龄>20或邮箱为null)的员工信息        UpdateWrapper updateWrapper = new UpdateWrapper<>();        //修改条件        updateWrapper.like("name", "a").and(i->i.gt("age", 20).isNull("email"));        //修改内容        updateWrapper.set("name", "lala").set("email", "www@cjc.com");        int i = userMapper.update(null, updateWrapper);        System.out.println(i);

LambdaQueryWrapper

作用:防止我们太笨,而把字段名写错进而提供了一个函数式接口来访问我们实体类中的某一个属性,当我们把属性访问之后,那么他就可以自动的获取属性所对应的字段名,来当作作为条件的哪个字段

        String name="a";        Integer ageBegin=null;        Integer ageEnd=30;        //主要避免了名称写错进而提供了直接访问表达式::        LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();        lambdaQueryWrapper.like(StringUtils.isNotBlank(name), User::getName,name)                          .ge(ageBegin!=null, User::getAge,ageBegin)                          .le(ageEnd!=null, User::getAge,ageEnd);        List users = userMapper.selectList(lambdaQueryWrapper);        System.out.println(users);

LambdaUpdateWrapper

        //查询用户名中包含a(年龄>20或邮箱为null)的员工信息        LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>();        //修改条件        updateWrapper.like(User::getName, "a").and(i->i.gt(User::getAge, 20).isNull(User::getEmail));        //修改内容        updateWrapper.set(User::getName, "lala").set(User::getEmail, "www@cjc.com");        int i = userMapper.update(null, updateWrapper);        System.out.println(i);

MP的分页插件

配置配置类(必然)

@Configurationpublic class MPConfig {    @Bean    public MybatisPlusInterceptor mybatisPlusInterceptor(){        //创建mybatisplus拦截器        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();        //向拦截器中添加分页插件        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));        return interceptor;    }}

MP实现分页 

//测试类内        //两个参数——当前页页码,每页信息条数        Page page = new Page<>(2,3);        //两个参数——分页对象,条件构造器        userMapper.selectPage(page, null);//因为我对所有的查询所以条件构造器为null——返回值还为page        //获取当前页数据        List records = page.getRecords();        System.out.println(records);        //获取总记录数        long total = page.getTotal();        System.out.println(total);        //获取总页数        long pages = page.getPages();        System.out.println(pages);        //是否有下一页        System.out.println(page.hasNext());        //是否有上一页        System.out.println(page.hasPrevious());

自定义分页功能

//自定义接口://mybatisplus提供的分页对象,必须为于第一个参数的位置Page selectPageVo(@Param("page") Page page,@Param("age") Integer age);//自定义配置文件sql    
        //测试类        Page page = new Page<>(2, 2);        userMapper.selectPageVo(page,20);        //获取当前页数据        List records = page.getRecords();        System.out.println(records);        //获取总记录数        long total = page.getTotal();        System.out.println(total);        //获取总页数        long pages = page.getPages();        System.out.println(pages);        //是否有下一页        System.out.println(page.hasNext());        //是否有上一页        System.out.println(page.hasPrevious());

MP乐观锁

在需要改变的实体类中加version注解

@Datapublic class Product {    private Long id;    private String name;    private Integer price;    @Version//用来标识乐观锁版本号字段    private Integer version;}

添加乐观锁插件 

@Configurationpublic class MPConfig {    @Bean    public MybatisPlusInterceptor mybatisPlusInterceptor(){        //创建mybatisplus拦截器        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();        //向拦截器中添加乐观锁插件        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());        return interceptor;    }}

测试 

注意:下面小王和小李拿的是同一个数据

        //小李查询商品价格        Product productLi = productMapper.selectById(1);        System.out.println("小李"+productLi.getPrice());        //小王查询商品价格        Product productWang = productMapper.selectById(1);        System.out.println("小王"+productWang.getPrice());        //小李将商品价格+50        productLi.setPrice(productLi.getPrice()+50);        productMapper.updateById(productLi);        //小王将商品价格-30        productWang.setPrice(productWang.getPrice()-30);        int result = productMapper.updateById(productWang);        if (result==0){            //操作失败后重试            Product productNew = productMapper.selectById(1);            productNew.setPrice(productNew.getPrice()-30);            productMapper.updateById(productNew);        }

通用枚举

实体类中有枚举类型,那么怎么将该枚举类型存入到数据库中呢

//为该枚举添加注解@Getterpublic enum SexEnum {    MALE(1,"男"),    FEMALE(2,"女");    @EnumValue//将注解所标识的属性的值存储到数据库中(因为数据库中存放的是数字)    private Integer sex;    private String sexName;    SexEnum(Integer sex, String sexName) {        this.sex = sex;        this.sexName = sexName;    }}

配置通用枚举扫描包

mybatis-plus.type-enums-package=cn.tedu.mybatisplus.enums

将有枚举的对象插入到数据库

MP自动填充功能

添加配置类

@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {    @Override    public void insertFill(MetaObject metaObject) {        this.setFieldValByName("created", new Date(), metaObject);        this.setFieldValByName("updated", new Date(), metaObject);    }    @Override    public void updateFill(MetaObject metaObject) {        this.setFieldValByName("updated", new Date(), metaObject);    }}

为实体类添加注解 

@Data@Accessors(chain = true)public class Product {    private Long id;    private String name;    private Integer price;    //在插入数据时自动填充    @TableField(fill = FieldFill.INSERT)    private Date created;    //在插入和更新操作时自动填充    @TableField(fill = FieldFill.INSERT_UPDATE)    private Date updated;    @Version//用来标识乐观锁版本号字段    private Integer version;}

测试 

        //测试        Product product = new Product();        product.setName("cake").setId(3L).setPrice(66);        int insert = productMapper.insert(product);        System.out.println(insert);

来源地址:https://blog.csdn.net/m0_60027772/article/details/126570742

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MyBatisPlus总结

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

MybatisPlus框架项目落地实践分析总结

这篇文章主要为大家介绍了MybatisPlus框架项目落地实践分析总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-03-01

python:yield总结

资源总结来源于以下各地:1.http://blog.donews.com/limodou/archive/2006/09/04/1028747.aspx2.http://blog.chinaunix.net/uid-26922865-id-
2023-01-31

CSS3总结

一、选择器1.通用选择器E~F:E后边所有和E同级的F2.属性选择器E[att^=’val’]:att属性中以val开头的E[att$=’val’]:以val结尾的E[att*=’val’]含有val的选择器3.伪类选择器E:nth-chi
2023-01-31
2023-09-21

python 总结

一.列表1.extend(列表独有功能)循环添加到一个列表中a.有列表users = ['张三',‘李四]   people = ['小明,王五']users.extend(people)   # 在users中添加people.exten
2023-01-31

oracle总结

1.创建表空间create tablespance 表名datafile ‘’;-- 放在的位置size --设置大小autoextend onnext ;--扩展大小-- 2删除表空间drop tablespance 表名;-- 创建序列increment
oracle总结
2014-09-13

总结--3

主线程创建的时候会默认创建Looper、HandlerThread则是内置Looper,除此之外其他的线程创建时是不会创建Looper的,需手动创健线程自己的Looper。子线程更新主线程创建的控件引发的错误:Only the origin
2023-01-31

Python-socket总结

socket是什么什么是socket所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。说白了就是一种通信机制。列入你和移动客服咨询问题时,会有一个客服
2023-01-31
2024-04-02

Mysql锁总结

数据库锁设计的初衷是处理并发问题。作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来 实现这些访问规则的重要数据结构根据加锁的范围,MySQL 里面的锁大致可以分成全局锁、表级锁和行锁三类全局锁全局锁就是对整个数据库实
Mysql锁总结
2014-11-05
2023-09-04

MySQL总结-3

1、连接 mysql -u username -ppassword -P 3306 -D database -hip2、列显示:"\G"mysql> select * from HUMMOCK_BLACK_LIST limit 1 \G; 
2023-01-31

PYthon signal总结

预设信号处理函数signal包的核心是使用signal.signal()函数来预设(register)信号处理函数,如下所示:singnal.signal(signalnum, handler)signalnum为某个信号,handler为
2023-01-31

编程热搜

目录