zoukankan      html  css  js  c++  java
  • mp使用

    介绍

    简介

    [MyBatis-Plus](https://github.com/baomidou/mybatis-plus)(简称 MP)是一个 [MyBatis](http://www.mybatis.org/mybatis-3/) 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 
    官网是这样说的:
    他们愿景成为mybatis的搭档,就像魂斗罗的1p和2p,**好基友搭配,干活不累**。
    

    特征

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

    支持数据库

    	mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、Firebird
    	Phoenix 、clickhouse 、Sybase ASE 、 OceanBase 、达梦数据库 、虚谷数据库 、人大金仓数据库 、南大通用数据库 、
    

    使用

    引入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--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>
        <!--lombok用来简化实体类-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    

    注意:引入mybatis-plus后不要在引入mybatis,避免版本差异问题

    编写实体类

    给类名加@TableName,详解:https://baomidou.com/guide/annotation.html#tablename
    给id字段写@TableId,详解:https://baomidou.com/guide/annotation.html#tableid
    给普通字段写@TableField,详解:https://baomidou.com/guide/annotation.html#tablefield
    
    注意名称与数据库对应。
    

    创建Mapper接口

    public interface UserMapper extends BaseMapper<User> {
    
    

    启动类加注解

    @MapperScan("xxx.xxx.xxx.mapper")
    

    加入配置

    # 配置SQL日志
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    # 配置自动驼峰式编码
    mybatis-plus.configuration.map-underscore-to-camel-case: false
    

    启动调用mapper的方法

    注意mapper,然后调用mapper的方法即可。
    我们会发现我们mapper中没有代码,但是仍然可以使用。
    

    常用CRUD方法

    插入Insert

    操作

    int resultLen = mapper.insert(T);
    

    注意:我们这里没有设置主键生成策略,默认是ID_WORKER(雪花算法)策略,

    主键生成策略

    # myabtisPlus的id生成策略默认是ID_WORKER全局唯一ID
    自增策略其实有很多,比如数据库自增,UUID,自己设计、redis原子操作等。各有各的好处坏处,比如数据库自增不利于分库分表,UUID不利于排序和存储、自己设计容易出bug,难度大(大佬请忽略)、redis生成有限制必须使用redis。
    参考资料:分布式系统唯一ID生成方案汇总:https://www.cnblogs.com/haoxinyue/p/5208136.html
    # 配置id的自增策略
    1、给某张表某个ID字段加:@TableId(type=IdType.xxxxx),具体看文档https://baomidou.com/guide/annotation.html#tableid
    2、全局设置:mybatis-plus.global-config.db-config.id-type=auto,具体也是看官网文档
    

    更新Update

    操作

    int result = mapper.update(T);
    注意:
        其SQL生成是动态的,比如说我们更新一个User对象,其中有三个字段id,name,age,然后我们创建一个User对象,然后只setAge(20),setId(1),不设置name,那么mybatisplus生成的SQL就是:update user set age = 20 where id = 1。
    

    自动填充

    这个是咋回事呢,比如说我们数据中有creatTime和updateTime,然后我们想在insert的时候让mybatisplus自动帮我们填充creatTime和updateTime,update的时候让mybatisplus帮我们自动更新updateTime,这个就是自动填充。

    操作如下:

    1、给字段加注解

    	@TableField(fill = FieldFill.INSERT) // 代表着插入的时候会填充值
        private Date createTime;
        //@TableField(fill = FieldFill.UPDATE)	// 代表着更新的时候会填充值
        @TableField(fill = FieldFill.INSERT_UPDATE)	// 代表着插入和更新会填充值
        private Date updateTime;
    

    2、写类实现MetaObjectHandler接口

    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {
        
        /*当insert的时候调用*/
        @Override
        public void insertFill(MetaObject metaObject) {
            this.setFieldValByName("createTime", new Date(), metaObject);
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
        
        /*当update的时候调用*/
        @Override
        public void updateFill(MetaObject metaObject) {
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
    }
    

    乐观锁

    使用场景:我们更新一条数据之前,希望这条数据没有被别人更新过。

    举例:有一名员工的工资salary是3000,这时人事经理想来将这salary改为2000,然后总经理想将salary改为5000,然后他们都填好了想修改的salary,然后人事经理先提交,然后总经理后提交,完了后我们人事经理发现咋钱越改越多呢,这个时候就出现了问题,这个就是丢失更新,解决办法可以这样,我们给加一个version字段,然后每次更改后都将version+1,只有当前version和待修改的version一致,那么才能修改,这个version就可以看成一个乐观锁。我们加了version以后,前面的例子最初version为1,人事经理改完后version为2,这时候总经理那里拿到的还是version为1的数据,它来修改的话,手里的version比数据库中的version低,故而不允许修改。

    那么myabtisplus里面就可以实现这个version。

    官方解释

    # 意图:
    	当要更新一条记录的时候,希望这条记录没有被别人更新
    # 乐观锁实现方式:
        取出记录时,获取当前version
        更新时,带上这个version
        执行更新时, set version = newVersion where version = oldVersion
        如果version不对,就更新失败
    

    那么如何使用

    1、插件配置:

    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
    

    2、数据库必须有标志version字段,然后实体类中加注解

    @Version
    private Integer version;
    
    注意:
        支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
    	整数类型下 newVersion = oldVersion + 1
    	newVersion 会回写到 entity 中
    	仅支持 updateById(id) 与 update(entity, wrapper) 方法
    	在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
    

    查询Select

    id查询:

    T t = mapper.selectById(id);
    

    多个id批量查询

    List<t> ts = mapper.selectBatchIds(Arrays.asList(1, 2, 3));
    

    条件查询

    HashMap<String, Object> map = new HashMap<>();
    map.put("name", "Helen");
    map.put("age", 18);
    List<T> users = mapper.selectByMap(map);
    

    Wrapper条件后面再说

    .......

    分页

    配置bean
        /**分页插件*/
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            return new PaginationInterceptor();
        }
    代码:
        Page<T> page = new Page<>(1,5);
        mkapper.selectPage(page, null);
        page.getRecords().forEach(System.out::println);
        System.out.println(page.getCurrent());
        System.out.println(page.getPages());
        System.out.println(page.getSize());
        System.out.println(page.getTotal());
        System.out.println(page.hasNext());
        System.out.println(page.hasPrevious());
    

    删除Delete

    操作

    id删除

    mapper.deleteById(id);
    

    批量删除

    int result=mapper.deleteBatchIds(Arrays.asList(8,9));
    

    条件查询

    HashMap<String, Object> map = new HashMap<>();
    map.put("name", "Helen");
    map.put("age", 18);
    int result = mapper.deleteByMap(map);
    

    Wrapper条件后面会说

    ...

    逻辑删除

    说起删除,应该分为两种:

    逻辑删除:给定某一个标志代表该条数据已经被删除。

    物理删除:真的删除了

    1、给实体类字段上加注解

    @TableLogic
    private Integer deleted;
    

    2、配置文件

    # 此为默认配置,如果你的删除和未删除的标志不同则可以在此配置
    mybatis-plus.global-config.db-config.logic-delete-value=1
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
    

    3、配置bean

    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }
    

    4、官网说明

    # 说明:
    	只对自动注入的sql起效:
    # 插入: 不作限制
    # 查找: 追加where条件过滤掉已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
    # 更新: 追加where条件防止更新到已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
    # 删除: 转变为 更新
    # 例如:
        删除: update user set deleted=1 where id = 1 and deleted=0
        查找: select id,name,deleted from user where deleted=0
    # 字段类型支持说明:
        支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)
        如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()
    # 附录:
        逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
        如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。
    # 备注:
    	字段值insert的时候,可以数据库默认值,可以自己set,使用自动填充功能
    

    性能分析日志

    配置插件

    参数说明:

    ​ 参数:maxTime: SQL 执行最大时长,超过自动停止运行,有助于发现问题。

    ​ 参数:format: SQL是否格式化,默认false。

    配置bean:

    /**
     * SQL 执行性能分析插件
     * 开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长
     */
    @Bean
    @Profile({"dev","test"})// 设置 dev test 环境开启,prod不建议开启
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(100);//ms,超过此处设置的ms则sql不执行
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }
    

    配置spring的dev环境

    #环境设置:dev、test、prod
    spring.profiles.active=dev
    

    我们可以自定义对应开发、测试、生产环境不同的配置文件,然后不同环境下我们去使用不同的配置文件,可以在启动的时候添加参数,就可以不改变配置的情况下动态的选择环境,启动代码的时候-d,具体百度。

    Wrapper介绍

    介绍

    	Wrapper:条件构造抽象类,最顶端父类
        	AbstractWrapper:用于查询条件封装,生成sql的where 条件
            	QueryWrapper:Entity对象封装操作类,不是用lambda语法
            	UpdateWrapper:Update条件封装,用于Entity对象更新操作
        	AbstractLambdaWrapper:Lambda语法使用Wrapper统一处理解析lambda获取column。
            	LambdaQueryWrapper:看名称也能明白就是用于Lambda语法使用的查询Wrapper
            	LambdaUpdateWrapper:Lambda更新封装Wrapper
    

    一般我们使用QueryWrapper。

    使用

    ge、gt、le、lt、isNull、isNotNull:

    	QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper
            .isNull("name")
            .ge("age", 12)
            .isNotNull("email");
        int result = userMapper.delete(queryWrapper);
        System.out.println("delete return count = " + result);
    /**
    ge:大于等于
    gt:大于
    le:小于等于
    lt:小于
    isNull:为空
    isNotNull:不为空
    */
    

    eq、ne:

    /**
    eq:相等
    ne:不相等
    */
    

    between、notBetween:

    /**
    between:在某一个边界
    notBetween:不在某一个边界
    */
    

    allEq:

    /**
    allEq:整个map的内容全都要全等
    */
    

    like、notLike、likeLeft、likeRight:

    /**
    like:两边like,%a%
    notLike:不like 
    likeLeft:左边like,%a
    likeRiter:右边like,a%
    */
    

    太多了,就不一一列举了。。。。

  • 相关阅读:
    CocosIDE导出Android APK的注意事项
    C++14尝鲜:Generic Lambdas(泛型lambda)
    silverlight调用WebService传递json接收绑定数据
    解决考试系统高并发数据载入不对问题
    汇编入门学习笔记 (九)—— call和ret
    Java SerialPort SDK
    how tomcat works 总结 二
    linux下多线程的调试
    垃圾回收GC:.Net自己主动内存管理 上(二)内存算法
    HDU-4973-A simple simulation problem.(线段树)
  • 原文地址:https://www.cnblogs.com/daihang2366/p/13560566.html
Copyright © 2011-2022 走看看