文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

MyBatisPlus总结

2023-10-18 10:58

关注

目录

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特点

MP框架结构

理解:

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 {}

注意:

@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 {}

注意:

一些操作 

查询总记录数

        //查询总记录数        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

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 资料下载
  • 历年真题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容
咦!没有更多了?去看看其它编程学习网 内容吧