zoukankan      html  css  js  c++  java
  • Mybatis-Plus使用整理

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

      官网:[https://baomidou.com/]

    • MyBatis-Plus是怎么增强的呢?

      已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,类似JPA但优于JPA;

      简介:[https://mp.baomidou.com/guide/]   

    • 导入依赖
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    ​
    <!--mybatis plus和springboot整合-->
    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.4.1</version>
    </dependency>
    

      

    • MyBatis-Plus配置控制台打印日志
    #配置mybatis plus打印sql日志
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    

      

    • BaseMapper使用

      Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能;

      API使用参考源码:com.baomidou.mybatisplus.core.mapper.BaseMapper

    • QueryWrapper使用

      查询包装类,可以封装多数查询条件,泛型指定返回的实体类;

      可以封装sql对象,包括where条件,order by排序,select哪些字段等等;

      核心API:

    eq:等于
    ne:不等于
    gt:大于
    ge:大于等于
    lt:小于
    le:小于等于
    or:拼接or
    between:两个值中间
    notBetween:不在两个值中间
    like:模糊匹配
    notLike:不像
    likeLeft:左匹配,eg: like '%a'
    likeRight:右边匹配,eg:like 'a%'
    isNull:字段为空
    in:in范围查询
    groupBy:分组
    orderByAsc:升序
    orderByDesc:降序
    having:having查询
    

      

      API使用参考源码:com.baomidou.mybatisplus.core.conditions.query.QueryWrapper

    • MyBatis-Plus 常用注解
      • @TableName 用于定义表名  
      • @TableId 用于定义表的主键

        • 属性
    value 用于定义主键字段名
    type 用于定义主键类型(主键策略 IdType)
        • 主键策略    
    IdType.AUTO          主键自增,系统分配,不需要手动输入
    IdType.NONE          未设置主键
    IdType.INPUT         需要自己输入 主键值
    IdType.ASSIGN_ID     系统分配 ID,用于数值型数据(Long,对应 mysql 中 BIGINT 类型)
    IdType.ASSIGN_UUID   系统分配 UUID,用于字符串型数据(String,对应 mysql 中 varchar(32) 类型)
      • @TableField 用于定义表的非主键字段
        • 属性    
    value:用于定义非主键字段名,用于别名匹配,假如Java对象属性和数据库属性不一样
    ​
    exist:用于指明是否为数据表的字段, true 表示是,false 为不是,假如某个java属性在数据库没对应的字段则要标记为false
    ​
    fill:用于指定字段填充策略(FieldFill,用的不多)
      字段填充策略:一般用于填充 创建时间、修改时间等字段
      FieldFill.DEFAULT         默认不填充
      FieldFill.INSERT          插入时填充
      FieldFill.UPDATE          更新时填充
      FieldFill.INSERT_UPDATE   插入、更新时填充
    

      

    • 分页配置
      • 旧版本写法(MyBatis-Plus 3.4.0之前)  
    @Bean
    public PaginationInterceptor paginationInterceptor() {
    	return new PaginationInterceptor();
    }
    

      

       参考源码:com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor

      

      • 新版本写法(MyBatis-Plus 3.4.0之后)
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    	MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    	interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    
    	return interceptor;
    }
    

      

      • 测试分页:  

        建表sql

    CREATE TABLE `banner` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `img` varchar(524) DEFAULT NULL COMMENT '图片',
      `url` varchar(524) DEFAULT NULL COMMENT '跳转地址',
      `weight` int(11) DEFAULT NULL COMMENT '权重',
      `version` int(11) DEFAULT '1',
      `deleted` int(11) DEFAULT '0' COMMENT '0是未删除,1是已经删除',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    

      

        实体类

    @Data
    @TableName("banner")
    public class BannerDO {
    
        @TableId(value = "id",type = IdType.AUTO)
        private Integer id;
    
        private String img;
    
        private String url;
    
        @TableField("weight")
        private Integer weight;
    
        @TableField(exist = false)
        private Date createTime;
    
        /**
         * 乐观锁版本号
         */
        @Version
        private Integer version;
    
    
        /**
         * 逻辑删除标识位
         */
        private Integer deleted;
    
    }
    

      

        分页测试:

    @Test
    public void testPage1() {
    	// 第1页,每页2条
    	Page<BannerDO> page = new Page<>(1, 2);
    	IPage<BannerDO> bannerDOIPage = bannerMapper.selectPage(page, null);
    	log.info("总条数" + bannerDOIPage.getTotal());
    	log.info("总页数" + bannerDOIPage.getPages());
    	log.info("当前页数:" + bannerDOIPage.getCurrent());
    	// 获取当前数据
    	log.info(bannerDOIPage.getRecords().toString());
    }
    

      

        执行结果如下:

      

       启用分页插件,MyBatis-Plus会先进行select count(*)对当前表进行统计之后再分页;

      • XML自定义分页的写法

        自定义Mapper

    public interface BannerMapper extends BaseMapper<BannerDO> {
    	IPage<BannerDO> customizeSelectPage(Page<?> page, @Param("weight") int weight);
    }
    

      

        自定义XML

    <select id="customizeSelectPage" resultType="BannerDO">
    	select id, img, url, weight, version, deleted from banner where weight=#{weight}
    </select>
    

      

        测试分页:

    @Test
    public void testPage2() {
    	// 第1页,每页2条
    	Page<BannerDO> page = new Page<>(1, 2);
    	IPage<BannerDO> bannerDOIPage = bannerMapper.customizeSelectPage(page, 2);
    	log.info("总条数" + bannerDOIPage.getTotal());
    	log.info("总页数" + bannerDOIPage.getPages());
    	log.info("当前页数:" + bannerDOIPage.getCurrent());
    	// 获取当前数据
    	log.info(bannerDOIPage.getRecords().toString());
    }
    

      

        执行结果如下:

      

      参考:[https://mp.baomidou.com/guide/page.html

    • MyBatis-Plus 自定义xml

      配置mapper路径,如果采用默认路径可以不配

    #默认配置路径
    mybatis-plus.mapper-locations=classpath*:/mapper/*Mapper.xml
    

      

    • MyBatis-Plus 全局配置文件
    #配置最新全局配置文件
    mybatis-plus.config-location = classpath*:mybatis-config.xml
      • 注意:config-location和configuration不能同时出现,需要注释配置文件里的相关配置

      mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    	<settings>
    		<!--控制台输出日志-->
    		<setting name="logImpl" value="STDOUT_LOGGING"/>
    	</settings>
    </configuration>
    

      

    • 配置文件配置 自定义xml映射的包扫描路径

      eg:

    #配置文件配置 自定义sql的包扫描 实体类的路径
    mybatis-plus.type-aliases-package=org.example.manager.model
    
    • MyBatis-Plus下划线转驼峰配置,默认就是true
    mybatis-plus.configuration.map-underscore-to-camel-case=true
    

      

    • MyBatis-Plus配置全局默认主键类型,实体类就不用加 @TableId(value = "id", type = IdType.AUTO)
    mybatis-plus.global-config.db-config.id-type=auto
    

      

    • MyBatis-Plus指定查询字段

      eg:

    List<BannerDO> bannerDOList = bannerMapper.selectList(new QueryWrapper<BannerDO>().select("id", "url"));
    

      题外话,关于SELECT * 与 SELECT指定字段的区别

      • 网络I/O

        SELECT * 会查出所有的字段,有些是不需要的,当应用程序和服务器不在同一个局域网时,字段过多会影响网络传输的性能

      • 索引

        在指定字段有索引的情况下,MySql是可以不用读磁盘的,直接使用索引里面的值就返回结果的;

        但用了SELECT *,这就会有其他列需要从磁盘中读取才会返回结果,这样就造成了额外的性能开销;

    • MyBatis-Plus乐观锁使用  

      乐观锁就是每次去拿数据的时候都认为别人不会修改,更新的时候会通过版本来判断别人是否修改了数据,如果数据被修改了就拒绝更新;

      java中的AtomicXXX原子类是通过CAS实现,CAS即比较并更新,属于乐观锁,性能较悲观锁有很大的提高;

      悲观锁适合写操作多的场景,乐观锁适合读操作多的场景,乐观锁的吞吐量会比悲观锁多;

      数据库的乐观锁大多是基于数据版本 (Version)记录机制实现;数据版本即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来 实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一;此时,将提交数据的版本数据与数据,库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据;

      使用:

      实体类增加version属性配置

    @Version
    private Integer version;
    

      

      增加乐观锁插件

    //乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    

      

      测试代码

    @Test
    public void testOptimisticLocker1() {
    	BannerDO bannerDO = new BannerDO();
    	//旧版本号,即查询出来的版本号需要做对比的
    	bannerDO.setVersion(1);
    	bannerDO.setId(8);
    	bannerDO.setUrl("www.baidu.com");
    	bannerMapper.updateById(bannerDO);
    }
    
    public void testOptimisticLocker2() {
    	BannerDO bannerDO = new BannerDO();
    	//旧版本号,即查询出来的版本号需要做对比的
    	bannerDO.setVersion(1);
    	bannerDO.setId(8);
    	bannerDO.setUrl("www.baidu.com");
    	bannerMapper.updateById(bannerDO);
    }
    

      

        testOptimisticLocker1执行前,数据库表中的数据;

      

         执行testOptimisticLocker1

      

       

        执行testOptimisticLocker2,更新失败

      

        注意:

      • 乐观锁数据类型支持int,integer,long,timestamp;
      • 仅支持updateById和update方法
    • MyBatis-Plus 逻辑删除配置使用

      逻辑删除只不过是更新了标记,不会真正的物理删除;

      使用方式:

      • 数据库增加逻辑删除的标识字段,如deleted,0是未删除,1表示删除;
      • 实体类增加属性配置@TableLogic 或者 在配置文件增加指定
    @TableLogic
    private Integer deleted;
      • 配置文件新增配置
    #删除是1
    mybatis-plus.global-config.db-config.logic-delete-value=1
    #未删除是0
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
    #逻辑删除的全局标识字段,如果java实体类没加注解@TableLogic,则可以配置这个
    mybatis-plus.global-config.db-config.logic-delete-field=deleted
    

      

       测试代码:

    public void testDeleteById() {
    	int rtn = bannerMapper.deleteById(8);
    	log.info("rtn:{}", rtn);
    }
    

      

      执行结果:  

      

       打印的sql为update,而不是delete;

      

    • Mybatis-Plus-Generator 代码自动生成工具使用

      AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率;
      底层是模板引擎技术,可以自定义生成的java类模板;

      导入依赖

    <!-- 代码自动生成依赖 begin -->
    <dependency>
    	<groupId>com.baomidou</groupId>
    	<artifactId>mybatis-plus-generator</artifactId>
    	<version>3.4.1</version>
    </dependency>
    <!-- velocity -->
    <dependency>
    	<groupId>org.apache.velocity</groupId>
    	<artifactId>velocity-engine-core</artifactId>
    	<version>2.0</version>
    </dependency>
    <!-- 代码自动生成依赖 end-->
    

      

      使用如下,配置按需修改:

    public class MyBatisPlusGenerator {
        public static void main(String[] args) {
            //1. 全局配置
            GlobalConfig config = new GlobalConfig();
            // 是否支持AR模式
            config.setActiveRecord(true)
                    // 作者
                    .setAuthor("")
                    // 生成路径,最好使用绝对路径
                    .setOutputDir("")
                    // 文件覆盖
                    .setFileOverride(true)
                    // 主键策略
                    .setIdType(IdType.AUTO)
                    // 数据库时间类型
                    .setDateType(DateType.ONLY_DATE)
                    // 设置生成的service接口的名字的首字母是否为I,默认Service是以I开头的
                    .setServiceName("%sService")
                    // 实体类结尾名称
                    .setEntityName("%sDO")
                    // 生成基本的resultMap
                    .setBaseResultMap(true)
                    // 不使用AR模式
                    .setActiveRecord(false)
                    // 生成基本的SQL片段
                    .setBaseColumnList(true);
    
            //2. 数据源配置
            DataSourceConfig dsConfig = new DataSourceConfig();
            // 设置数据库类型
            dsConfig.setDbType(DbType.MYSQL)
                    .setDriverName("com.mysql.cj.jdbc.Driver")
                    .setUrl("")
                    .setUsername("")
                    .setPassword("");
    
            //3. 策略配置globalConfiguration中
            StrategyConfig stConfig = new StrategyConfig();
    
            //全局大写命名
            stConfig.setCapitalMode(true)
                    // 数据库表映射到实体的命名策略
                    .setNaming(NamingStrategy.underline_to_camel)
                    // 使用lombok
                    .setEntityLombokModel(true)
                    // 使用restcontroller注解
                    .setRestControllerStyle(true)
                    // 生成的表, 支持多表一起生成,以数组形式填写
                    // 两个方式,直接写,或者使用命令行输入
                    //.setInclude("");
                    .setInclude(scanner("表名,多个英文逗号分割").split(","));
    
            //4. 包名策略配置
            PackageConfig pkConfig = new PackageConfig();
            pkConfig.setParent("org.example.manager")
                    .setMapper("mapper")
                    .setService("service")
                    .setController("controller")
                    .setEntity("model")
                    .setXml("mapper");
            //5. 整合配置
            AutoGenerator ag = new AutoGenerator();
            ag.setGlobalConfig(config)
                    .setDataSource(dsConfig)
                    .setStrategy(stConfig)
                    .setPackageInfo(pkConfig);
    
            //6. 执行操作
            ag.execute();
            System.out.println("======= 代码生成完毕  ========");
        }
        
        /**
         * <p>
         * 读取控制台内容
         * </p>
         */
        public static String scanner(String tip) {
            Scanner scanner = new Scanner(System.in);
            StringBuilder help = new StringBuilder();
            help.append("请输入" + tip + ":");
            System.out.println(help.toString());
            if (scanner.hasNext()) {
                String ipt = scanner.next();
                if (StringUtils.isNotBlank(ipt)) {
                    return ipt;
                }
            }
            throw new MybatisPlusException("请输入正确的" + tip + "!");
        }
    }
    

      

     
  • 相关阅读:
    Android Broadcast
    Android 向服务器发送XML数据及调用webservice
    Android ViewPager相册横向移动
    Android 启动模式
    SQL Server忘记sa用户密码处理方案
    ArcGIS 10的色带重复问题
    隐藏TabControl中的TabPage
    ArcMap工具箱中的工具不全,工具带有“锁”图标问题
    ArcEngine开发——根据图层名称获取对应图层
    获取本地网络中可用的SQL Server实例信息
  • 原文地址:https://www.cnblogs.com/coder-zyc/p/14642852.html
Copyright © 2011-2022 走看看