zoukankan      html  css  js  c++  java
  • 使用mybatis plus 操作数据库

    mybatis plus 是基于mybatis 的一个增强包,比 mybatis 更加容易使用。

    特点:

    1.分页支持

    2.支持自定义查询。

    3.简单的情况下,不需要写map.xml 文件

    4.支持租户过滤

    下面介绍一下 它的使用方法

    1.引入jar包。

    在 pom.xml 增加

    <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.1.0</version>
            </dependency>
    
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.10</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>

    2.配置使用数据源

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/wuxianji?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          # 下面为连接池的补充设置,应用到上面所有数据源中
          # 初始化大小,最小,最大
          initial-size: 5
          min-idle: 5
          max-active: 20
          # 配置获取连接等待超时的时间
          max-wait: 60000
          # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
          time-between-eviction-runs-millis: 60000
          # 配置一个连接在池中最小生存的时间,单位是毫秒
          min-evictable-idle-time-millis: 300000
          validation-query: SELECT 1 FROM DUAL
          test-while-idle: true
          test-on-borrow: false
          test-on-return: false
          # 打开PSCache,并且指定每个连接上PSCache的大小
          pool-prepared-statements: true
          #   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
          max-pool-prepared-statement-per-connection-size: 20
          filters: stat,wall
          use-global-data-source-stat: true
          # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
          connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
          # 配置监控服务器
          stat-view-servlet:
            login-username: admin
            login-password: 123456
            reset-enable: false
            url-pattern: /druid/*
            # 添加IP白名单
            #allow:
            # 添加IP黑名单,当白名单和黑名单重复时,黑名单优先级更高
            #deny:
          web-stat-filter:
            # 添加过滤规则
            url-pattern: /*
            # 忽略过滤格式
            exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"

    这里我们使用 druid 作为数据源

    3.配置 mybatis plus 

    mybatis-plus:
      mapper-locations: classpath:/mapper/**/*.xml
      global-config:
          refresh: true # 刷新xml文件
          db-config:
                logic-delete-value: 1 #默认值1
                logic-not-delete-value: 0 #默认值0

     这里指定了mapper xml 文件的位置。

    4. 创建mybatis plus 配置java 文件

    package com.example.config;
    
    import com.baomidou.mybatisplus.core.injector.ISqlInjector;
    import com.baomidou.mybatisplus.core.parser.ISqlParser;
    import com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator;
    import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
    import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
    import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
    import net.sf.jsqlparser.expression.LongValue;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import net.sf.jsqlparser.expression.Expression;
    import net.sf.jsqlparser.expression.LongValue;
    
    
    import java.util.ArrayList;
    import java.util.List;
    
    @Configuration
    @MapperScan("com.example.demo.dao")
    public class MybatisPlusConfig {
    
        @Bean
        public PerformanceInterceptor performanceInterceptor(){
            return new PerformanceInterceptor();
        }
    
        @Bean
        public ISqlInjector sqlInjector() {
            return new LogicSqlInjector();
        }
    
        /**
         * 分页插件
         */
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            PaginationInterceptor paginationInterceptor= new PaginationInterceptor();
    
            List<ISqlParser> sqlParserList = new ArrayList<>();
            TenantSqlParser tenantSqlParser = new TenantSqlParser();
            tenantSqlParser.setTenantHandler(new TenantHandler() {
                @Override
                public Expression getTenantId() {
                    return new LongValue(1L);
                }
    
                @Override
                public String getTenantIdColumn() {
                    return "tenant_id";
                }
    
                @Override
                public boolean doTableFilter(String tableName) {
                    // 这里可以判断是否过滤表
    
                if ("User_".equals(tableName)) {
                    return true;
                }
                    return false;
                }
            });
            sqlParserList.add(tenantSqlParser);
            paginationInterceptor.setSqlParserList(sqlParserList);
            return paginationInterceptor;
        }
    }

    这里支持性能分析,逻辑删除,租户过滤,物理分页。

    5.下面以一个操作一个用户表为例,介绍一下 具体的用法。

    5.1 创建一个用户表

    CREATE TABLE `user_` (
      `id_` bigint(11) NOT NULL DEFAULT '0',
      `name_` varchar(255) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      `address` varchar(100) DEFAULT NULL,
      `isDelete` int(11) DEFAULT NULL,
      PRIMARY KEY (`id_`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    5.2 创建对应的User.java类

    package com.example.demo.model;
    
    
    import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableLogic;
    import com.baomidou.mybatisplus.annotation.TableName;
    
    @TableName(value = "User_")
    public class User {
    
        @TableId(value="id_")
        private Long id;
    
    
    
        @TableField(value="name_")
        private String name;
        private Integer age;
        private String address;
        @TableLogic
        @TableField(value="isDelete")
        private Integer isDelete;
    
      
    
      
    }

    这里去掉了get 和 set 方法。

    5.3 创建 DAO操作数据库

    package com.example.demo.dao;
    
    import  com.example.demo.model.*;
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    
    import java.util.Map;
    
    public interface UserMapper extends BaseMapper<User> {
    
        int updName(Map<String,Object> params);
    }

    这个类继承了 BaseMapper 接口,自动有增查改删操作。

    5.4 开始测试

    1.列表查询

     private UserMapper userMapper;
    
        //@Test
        public void testSelect() {
            System.out.println(("----- selectAll method test ------"));
            List<User> userList = userMapper.selectList(null);
            Assert.assertEquals(5, userList.size());
            userList.forEach(System.out::println);
        }

    2.增加用户

    public void add() {
            User user=new User();
            user.setId(14L);
            user.setName("关羽");
            user.setAge(12);
            userMapper.insert(user);
        }

    3.更新实体对象

     public void upd() {
            User user=new User();
            user.setId(13L);
            user.setName("zyg");
            user.setAge(13);
            userMapper.updateById(user);
        }

    4.自定义条件更新

    public void updWrap() {
            User user=new User();
            user.setAddress("广州");
            user.setAge(23);
            userMapper.update(user,new UpdateWrapper<User>().eq("name_","a").or().eq("name_","b"));
        }

    这个意思是他会根据姓名 为 a 或 b 的用户更新他的地址和年龄字段。

    5.根据 MAP 传值更新

     public void updName() {
            Map<String,Object> params=new HashMap<>();
    
            params.put("id",14);
            params.put("name","趙雲");
    
            int i= userMapper.updName(params);
            System.err.println(i);
        }

    这里我们需要在 User.xml 中增加

    <update id="updName" parameterType="java.util.HashMap">
            update user_ set name_=#{name} where id_=#{id}
        </update>

    也需要在UserMapper 内中增加方法

    int updName(Map<String,Object> params);

    6.分页获取数据

    public  void getPage(){
            Page<User> page = new Page<>(1, 5);
            IPage<User> userIPage = userMapper.selectPage(page, null);
            System.err.println(userIPage.getRecords());
    
        }

    这个需要配合MybatisPlusConfig 的分页配置,才可以生效。

    7.当分页返回的数据不是 User 对象时,我们可以返回 Map对象。

    public  void getPageMap(){
            Page page = new Page<>(1, 5);
    
            Wrapper wrapper=new QueryWrapper();
            ((QueryWrapper) wrapper).ge("id_",2);
    
            IPage<Map<String,Object>> userIPage = userMapper.selectMapsPage(page,wrapper);
            System.err.println(userIPage.getRecords());
    
        }

    这里我们查询Id_ 大于 2的用户分页列表。

    8.逻辑删除用户

    如果平台中数据不需要做实际删除,我们可以配置逻辑删除

    配置方法如下:

    MybatisPlusConfig  中指定了 

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

    配置这个就支持逻辑删除

    application.yml配置如下:

    mybatis-plus:
    mapper-locations: classpath:/mapper/**/*.xml
    global-config:
    refresh: true # 刷新xml文件
    db-config:
    logic-delete-value: 1 #默认值1
    logic-not-delete-value: 0 #默认值0
    这里指定逻辑删除 删除标记 为1 表示删除 为0 表示正常。
    User 对象 需要指定
    @TableLogic
    @TableField(value="isDelete")

    指定逻辑删除字段。

    删除代码

    public  void delById(){
            userMapper.deleteById(1L);
        }

    这样我们执行这个删除时,后端并不执行删除操作。

     Time:9 ms - ID:com.example.demo.dao.UserMapper.deleteById
    Execute SQL:UPDATE User_ SET isDelete = 1 WHERE id_ = 1 AND isDelete = 0

    后端执行的语句为 将 删除标记更新为1

    9.分页配置根据租户查询。

    需要配置

     List<ISqlParser> sqlParserList = new ArrayList<>();
            TenantSqlParser tenantSqlParser = new TenantSqlParser();
            tenantSqlParser.setTenantHandler(new TenantHandler() {
                @Override
                public Expression getTenantId() {
                    return new LongValue(1L);
                }
    
                @Override
                public String getTenantIdColumn() {
                    return "tenant_id";
                }
    
                @Override
                public boolean doTableFilter(String tableName) {
                    // 这里可以判断是否过滤表
    
                if ("User_".equals(tableName)) {
                    return true;
                }
                    return false;
                }
            });
            sqlParserList.add(tenantSqlParser);
            paginationInterceptor.setSqlParserList(sqlParserList);

    1.指定租户ID字段

    2.返回租户ID值 

     @Override
                public Expression getTenantId() {
                    return new LongValue(1L);
                }

    3.允许表过滤

    有些表是不需要通过租户过滤的,可以修改方法

     @Override
                public boolean doTableFilter(String tableName) {
                    // 这里可以判断是否过滤表
                    if ("User_".equals(tableName)) {
                        return true;
                    }
                    return false;
                }

    10.乐观锁支持

    乐观锁的原理是,每一条数据都带有一个版本。

    比如当前都版本为1.

    在更新数据时,会将版本加一进行更新,如果A 进行更新,那么这个时候版本变为 2,如果B 同A一起发起更新,那么这个时候就更新不到,给出提示。

    配置方法:

    @Version
        private Integer version;

    User 类中增加一个字段 为 version

    配置增加乐观锁

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

    编写更新代码

    public void upd() {
            User user=new User();
            user.setId(13L);
            user.setName("zyg");
            user.setAge(13);
            user.setVersion(1);
            if(  userMapper.updateById(user)>0){
                System.err.println("更新成功");
            }
            else {
                System.err.println("被其他人更新");
            }
        }

    执行上面的代码

     Time:7 ms - ID:com.example.demo.dao.UserMapper.updateById
    Execute SQL:UPDATE User_ SET name_ = 'zyg', age = 13, version = 2 WHERE id_ = 13 AND version = 1

    这里我们可以看到他会自动将版本字段加1,如果执行成功就变成了2,当第二个人执行更新的时候,还是用版本1 进行更新,数据就更新不到了。

  • 相关阅读:
    java 堆栈 附图
    synchronized、volatile关键字
    Swift随笔
    java |、&、~、>>、<<运算符的作用。
    java双向链表示意图
    java单链表
    List集合的过滤之lambda表达式
    SQL hint作用
    创建触发器的一般语法
    多线程创建方式
  • 原文地址:https://www.cnblogs.com/yg_zhang/p/10736442.html
Copyright © 2011-2022 走看看