zoukankan      html  css  js  c++  java
  • Mybatisplus基本用法

    1.简介

    官网:https://mp.baomidou.com

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

    2.入门

    源码:https://github.com/zhongyushi-git/mybatis-plus-demo.git

    2.1数据库准备

    使用mysql数据库创建数据,执行脚本在根目录下的sql目录下

    2.2环境搭建

    1)新建一个SpringBoot的项目,导入需要的坐标

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--mysql数据库依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.9</version>
            </dependency>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.8</version>
            </dependency>

    2)yml配置

    #数据源配置
    spring:
      datasource:
        #使用阿里巴巴的druid
        type: com.alibaba.druid.pool.DruidDataSource
        #配置数据库的路径和用户名密码
        url: jdbc:mysql://127.0.0.1:3306/mybatisplus?useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true
        username: root
        password: zys123456

    2.3引入mybatis-plus开发

    1)导入依赖

          <!--mybatis-plus-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.4.0</version>
            </dependency>

    2)创建实体类

    @Data
    public class User {
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }

    3)创建dao继承BaseMapper

    package com.zys.mybatisplusdemo.dao;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.zys.mybatisplusdemo.entity.User;
    
    public interface UserDao extends BaseMapper<User> {
    
    }

    4)在启动类上加mapper扫描

    @SpringBootApplication
    @MapperScan("com.zys.mybatisplusdemo.dao")
    public class MybatisPlusDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(MybatisPlusDemoApplication.class, args);
        }
    
    }

    5)创建controller

    @RestController
    @RequestMapping("/users")
    public class UserController {
    
        @Autowired
        private UserDao userDao;
    
        @GetMapping("/list")
        public List<User> userList(){
            List<User> users = userDao.selectList(null);
            return  users;
        }
    }

    为了演示方便,这里省略了service的部分而直接调用了dao层,具体见源码。

    如果添加了mapper.xml,那么需要配置xml的位置,否则会出现无法绑定。

    mybatis-plus.mapperLocations=classpath*:mapper/*.xml

    6)测试

    启动项目,访问http://localhost:8080/users/list即可看到所有的数据。

    3.常用注解

    3.1@TableName

    其用来将实体对象与数据库表名进行对应。当实体名与数据库表名不一致时使用。

    3.2@TableId

    其是主键注解,指明是主键,默认把id作为主键。属性type用来指定类型:

    1)IdType.AUTO是自动增长;

    2)IdType.ASSIGN_UUID是String类型的uuid

    3)IdType.INPUT是根据用户的输入作为主键

    3.3@TableField

    其是表的其他字段注解。属性exist用来指明是否是数据库的字段,值为false时不映射数据库表字段。详细的介绍见后续章节,这里的说明已供使用。

    3.4注解开发

    1)首先将数据库中表名改为t_user,然后实体User加上注解@TableName

    @Data
    @TableName(value = "t_user")
    public class User {
         ......      
    }

    启动项目,访问http://localhost:8080/users/list可以正常返回数据。

    2)将数据库中表t_user的字段id改为t_id,然后修改实体User的属性id并设置自动增长

    @Data
    @TableName(value = "t_user")
    public class User {
        //指定自动增长
        @TableId(value = "t_id",type = IdType.AUTO)
        private Long id;
        ......
    }

    3)将数据表t_user的字段name改为t_name,然后修改实体User的属性name

     @TableField(value = "t_name")
     private String name;

    4)在实体User上添加一个属性,设置不作为数据库的字段

     //不映射数据库表字段
        @TableField(exist = false)
        private String aaa;

    启动项目,同上进行访问,数据正常返回。在实际开发过程中,可根据需求使用注解。

    4.条件构造器

    方法 说明 示例
    eq 等于

    allEq({id:1,name:"老王",age:null})--->

    id = 1 and name = '老王' and age is null

    allEq 全等于 eq("name", "老王")--->name = '老王'
    ne 不等于 ne("name", "老王")--->name <> '老王'
    gt 大于 gt("age", 18)--->age > 18
    ge 大于等于 ge("age", 18)--->age >= 18
    lt 小于 lt("age", 18)--->age < 18
    le 小于等于 le("age", 18)--->age <= 18
    between BETWEEN 值1 AND 值2 between("age", 18, 30)--->age between 18 and 30
    notBetween NOT BETWEEN 值1 AND 值2 notBetween("age", 18, 30)--->age not between 18 and 30
    like LIKE '%值%' like("name", "王")--->name like '%王%'
    notLike NOT LIKE '%值%' notLike("name", "王")--->name not like '%王%'
    likeLeft LIKE '%值' likeLeft("name", "王")--->name like '%王'
    likeRight LIKE '值%' likeRight("name", "王")--->name like '王%'
    isNull 字段为null isNull("name")--->name is null
    isNotNull 字段不为null isNotNull("name")--->name is not null
    in 同数据库in in("age",{1,2,3})--->age in (1,2,3)
    notIn 同数据库not in notIn("age",{1,2,3})--->age not in (1,2,3)
    inSql 相当于子查询和in

    inSql("id", "select id from table where id < 3")--->

    id in (select id from table where id < 3)

    notInSql 相当于子查询和not in

    notInSql("id", "select id from table where id < 3")--->

    id not in (select id from table where id < 3)

    groupBy 同数据库group by groupBy("id", "name")--->group by id,name
    orderBy/orderByDesc 同数据库order by 字段/order by  字段 desc orderBy("id")--->order by id ASC
    having 同数据库having having("sum(age) > 10")--->having sum(age) > 10
    or/and 同数据库or/and 略 
    netsted 正常嵌套 不带 AND 或者 OR nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着')
    apply 字符串拼接

    apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->

    date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

    last 拼接在最后,谨慎使用 last("limit 1")---> limit 1
    exists/notExists 拼接sql exists("select id from table where age = 1")--->exists (select id from table where age = 1)
    select 指定要查询的字段 select("id", "name", "age")--->只查询这三个字段的内容
    set 全局修改 set("name", "")--->数据库字段值变为空字符串

    5.CRUD操作

    只进行简单的介绍,具体需求请自行开发,都是在这个基础上进行的。需要说明的是,下面的增加和修改操作,只会根据对象中存在不为null的属性来操作数据,当数据为null时不会改变数据库中的数据。

    5.1添加insert

        @PostMapping("/")
        public String save(User user){
            int count = userDao.insert(user);
            if(count!=0){
                return "添加成功";
            }else{
                return "添加失败";
            }
        }

    5.2删除delete

    根据主键删除

      @DeleteMapping("/{id}")
        public String delete(@PathVariable("id")long id){
            int count = userDao.deleteById(id);
            if(count!=0){
                return "删除成功";
            }else{
                return "删除失败";
            }
        }

    5.3修改update

    根据id进行修改

    @PutMapping("/")
        public String update(User user){
            int count = userDao.updateById(user);
            if(count!=0){
                return "修改成功";
            }else{
                return "修改失败";
            }
        }

    5.4简单查询

    5.4.1selectList

    在入门时,controller中设置的查询条件是null,实际上里面需要传递一个QueryWrapper<T>类型的对象,调用dao的selectList(),此对象中才有上面的那些方法。

    1)查询年龄大于等于24的信息

        @GetMapping("/list")
        public List<User> userList(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            //设置查询条件
            queryWrapper.ge("age",24);//查询年龄大于等于24的信息
            List<User> users = userDao.selectList(queryWrapper);
            return  users;
        }

    2)查询名字中含有‘o’的信息

    queryWrapper.like("name","o");

    5.4.2selectById

    根据主键查询

     @GetMapping("/{id}")
        public User selectById(@PathVariable("id")long id){
            return userDao.selectById(id);
        }

    5.4.3selectCount

    查询符合条件的条数,一般和selectList结合使用。

     @GetMapping("/list")
        public Map<String,Object> userList(){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            //设置查询条件
            queryWrapper.like("name","o");
            List<User> users = userDao.selectList(queryWrapper);
            Integer integer = userDao.selectCount(queryWrapper);
            Map<String,Object> map=new HashMap<>();
            map.put("data",users);
            map.put("total",integer);
            return  map;
        }

    5.5分页查询

    5.5.1分页插件配置

    新建一个类配置其分页

    package com.zys.mybatisplusdemo.config;
    
    import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    /**
     * @Aauthor yushizhong
     * @Date 2020/5/17 16:19
     * @Dec MybatisPlus分页配置
     */
    @EnableTransactionManagement
    @Configuration
    @MapperScan("com.zys.mybatisplusdemo.dao")
    public class MybatisPlusConfig {
    
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
            return paginationInterceptor;
        }
    }

    5.5.2单表分页查询

    @GetMapping("/list")
        public IPage<User> userList(Integer curr,Integer limit){
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            //设置分页,默认值是1,10
            IPage<User> page=new Page<>(curr,limit);
            IPage<User> user = userDao.selectPage(page, queryWrapper);
            return  user;
        }

    5.5.3单表自定义分页查询

    有时使用默认的分页查询无法实现需要的功能时,可以自定义分页查询。

    先分析一下其自带的分页的方法,打开源码,看到接口中的selectPage方法:

    <E extends com.baomidou.mybatisplus.core.metadata.IPage<T>> E selectPage(E page,
    @org.apache.ibatis.annotations.Param("ew") com.baomidou.mybatisplus.core.conditions.Wrapper<T> queryWrapper);

    那么自定义也就是模仿其写法,步骤如下:

    1)在dao的接口中定义方法

     IPage<User> selectPageList(IPage<User> page, @Param(Constants.WRAPPER) QueryWrapper<User> queryWrapper);

    对第二个参数queryWrapper使用了@Param注解起别名,其名称使用的是常量的值(实际值是ew),常量的定义也是由官方定义好的,截图如下:

    2)在xml中编写sql

        <select id="selectPageList" resultType="com.zys.mybatisplusdemo.entity.User">
            select * from user ${ew.customSqlSegment}
        </select>

    那么后面的条件就直接使用"${ew.customSqlSegment}"进行代替了,它会根据设置的条件去查询。

    5.5.4多表自定义分页查询

    多表分页和单表的分页原来是一样的道理。现假设有两个表,t_student(学生表)和t_clazz(班级表)

    1)先创建两个表

    CREATE TABLE `clazz` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(50) DEFAULT NULL COMMENT '班级名称',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    CREATE TABLE `student` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(20) DEFAULT NULL COMMENT '学生姓名',
      `clazzId` int(11) DEFAULT NULL COMMENT '班级id',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
    
    insert into clazz values(1,'计算机1班'),(2,'计算机2班'),(3,'计算机3班');
    insert into student values(null,'赵敏',1),(null,'张明',3),(null,'李慧',3),(null,'赵美美',2),(null,'张峰',2),(null,'孙强',2);

    2)创建学生实体类

    @Data
    @TableName(value = "user")
    public class Student {
    
        @TableId(value = "id",type = IdType.AUTO)
        private Long id;
    
        @TableField(value = "name")
        private String name;
    
        @TableField(value = "clazzId")
        private Integer clazzId;
    
        @TableField(exist = false)
        private String clazzName;
    }

    3)创建controller接口

        @GetMapping("/list")
        public JSONObject getList(Integer curr, Integer limit) {
            QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
            queryWrapper.like("t1.name", "");
            IPage<Student> page = new Page<>(curr, limit);
            IPage<Student> stu = studentDao.selectPageList(page, queryWrapper);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("data", stu.getRecords());
            jsonObject.put("total", stu.getTotal());
            return jsonObject;
            
        }

    4)在dao接口定义方法

    IPage<Student> selectPageList(IPage<Student> page, @Param(Constants.WRAPPER) QueryWrapper<Student> queryWrapper);

    5)在xml编写sql

    <select id="selectPageList" resultType="com.zys.mybatisplusdemo.entity.Student">
            select t1.*,t2.name "clazzName" from student t1
            left join clazz t2 on t1.clazzId = t2.id
             ${ew.customSqlSegment}
    </select>

    6)调用此接口,数据可以正常查询。执行日志如下:

    当然,对于多表查询,如果使用默认的条件查询不能满足要求,可以把QueryMapper换成Mmap,那么在xml中使用对应的参数查询即可。 不过这种方式有些麻烦,但是可以实现更为复杂的需求

    dao接口的方法:

    IPage<Student> selectPageList2(IPage<Student> page, @Param(Constants.WRAPPER)Map<String, Object> map);

    xml的sql:

        <select id="selectPageList2" resultType="com.zys.mybatisplusdemo.entity.Student">
            select t1.*, t2.name "clazzName"
            from student t1
                     left join clazz t2 on t1.clazzId = t2.id
            <where>
                <if test="ew.name != null and ew.name != ''">
                    and t1.name like concat('%',#{ew.name},'%')
                </if>
            </where>
        </select>

    需要注意的是,在if标签中也需要带ew,否则会报错。

    6.代码生成器

    代码生成器自动生成包及需要的类名,节省开发的时间。前提是数据库中表已经建好,原因是它根据数据库表进行创建的。

    首先导入依赖

         <!--mybatis-plus代码生成器-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-generator</artifactId>
                <version>3.4.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity-engine-core</artifactId>
                <version>2.2</version>
            </dependency>

    创建生成器类,然后执行main方法

    package com.zys.mybatisplusdemo.config;
    
    import com.baomidou.mybatisplus.core.toolkit.StringPool;
    import com.baomidou.mybatisplus.generator.AutoGenerator;
    import com.baomidou.mybatisplus.generator.InjectionConfig;
    import com.baomidou.mybatisplus.generator.config.*;
    import com.baomidou.mybatisplus.generator.config.po.TableInfo;
    import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
    import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Aauthor yushizhong
     * @Date 2020/5/17 16:45
     * @Dec 代码生成器
     */
    public class CodeGenerator {
    
        public static void main(String[] args) {
    
            // 代码生成器
            AutoGenerator map = new AutoGenerator();
    
            // 全局配置
            GlobalConfig globalConfig = new GlobalConfig();
            //配置生成文件的输出目录
            globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
            //设置开发人员名称
            globalConfig.setAuthor("yushizhong");
            //是否打开输出目录
            globalConfig.setOpen(false);
            //mapper 命名方式
            globalConfig.setMapperName("%sDao");
            //service 命名方式
            globalConfig.setServiceName("%sService");
            map.setGlobalConfig(globalConfig);
    
            //数据源配置
            DataSourceConfig dataSourceConfig = new DataSourceConfig();
            //数据库的路径
            dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=CTT");
            //数据库驱动名称
            dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
            //数据库的登录用户名
            dataSourceConfig.setUsername("root");
            //数据库的登录密码
            dataSourceConfig.setPassword("123456");
            map.setDataSource(dataSourceConfig);
    
            // 包配置
            PackageConfig pc = new PackageConfig();
            //设置父包名
            pc.setParent("com.zys.mybatisplusdemo");
            pc.setMapper("dao");
            map.setPackageInfo(pc);
    
            // 自定义配置
            InjectionConfig cfg = new InjectionConfig() {
                @Override
                public void initMap() {
                }
            };
            String templatePath = "/templates/mapper.xml.vm";
            // 自定义输出配置
            List<FileOutConfig> focList = new ArrayList<>();
            // 自定义配置会被优先输出
            focList.add(new FileOutConfig(templatePath) {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    //设置xml的输出路径
                    return System.getProperty("user.dir") + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
                }
            });
            cfg.setFileOutConfigList(focList);
            map.setCfg(cfg);
    
            // 配置模板
            TemplateConfig templateConfig = new TemplateConfig();
            //在代码总不生成xml
            templateConfig.setXml(null);
            map.setTemplate(templateConfig);
    
            // 策略配置
            StrategyConfig strategy = new StrategyConfig();
            //数据库表映射到实体的命名策略:把下划线变成大写
            strategy.setNaming(NamingStrategy.underline_to_camel);
            //数据库表字段映射到实体的命名策略:把下划线变成大写
            strategy.setColumnNaming(NamingStrategy.underline_to_camel);
            //是否使用lombok
            strategy.setEntityLombokModel(true);
            strategy.setRestControllerStyle(true);
            // 写于父类中的公共字段
            strategy.setSuperEntityColumns("id");
            strategy.setControllerMappingHyphenStyle(true);
            //表前缀
            strategy.setTablePrefix(pc.getModuleName() + "_");
            map.setStrategy(strategy);
    
            //执行
            map.execute();
        }
    
    
    }

    7.实现缓存

    对于有些查询比较频繁的数据,可以放到缓存中,这里就以redis为例。mybatis-plus的缓存和mybatis的缓存实现原理类似,也有区别,mybatis的缓存实现请参考https://www.cnblogs.com/zys2019/p/11447169.html#_label7

    7.1实战演练

    1)导入redis的依赖,配置redis数据库参数(见源码)

    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    2)在配置文件中开启缓存

    mybatis-plus:
      configuration:
        #开启缓存
        cache-enabled: true

    如果不开启,那么缓存就不会生效。

    3)获取spring创建的工厂

    package com.zys.mybatisplusdemo.util;
    
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author zhongyushi
     * @date 2020/9/16 0016
     * @dec 获取spring创建的工厂
     */
    @Configuration
    public class ApplicationContextUtil implements ApplicationContextAware {
    
        private static ApplicationContext applicationContext;
    
        //把非spring创建好的工厂赋值给applicationContext,applicationContext在这个应用中是唯一的
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    
        //此创建好工厂后再获取对象
        public static Object getBean(String beanName){
            return applicationContext.getBean(beanName);
        }
    }

    4)创建redis缓存配置类,实现Cache,重写方法

    package com.zys.mybatisplusdemo.config;
    
    import com.zys.mybatisplusdemo.util.ApplicationContextUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.cache.Cache;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     * @author zhongyushi
     * @date 2020/9/28 0028
     * @dec MybatisPlus缓存配置,使用redis作为缓存服务器
     */
    @Slf4j
    public class MybatisPlusCache implements Cache {
        // 读写锁
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
    
        //这里使用了redis缓存,使用springboot自动注入
        private RedisTemplate<String, Object> redisTemplate;
    
        private String id;
    
        //是mybatis必须要求的,必写。此id是xml中的namespace的值
        public MybatisPlusCache(final String id) {
            if (id == null) {
                throw new IllegalArgumentException("未获取到缓存实例id");
            }
            this.id = id;
        }
    
        //返回cache的唯一名称
        @Override
        public String getId() {
            return this.id;
        }
    
        //缓存存值
        @Override
        public void putObject(Object key, Object value) {
            //id是namespace的值,key是方法名,value是查询的结果
            getRedisTemplate().opsForHash().put(id, key.toString(), value);
        }
    
        //缓存取值
        @Override
        public Object getObject(Object key) {
            return getRedisTemplate().opsForHash().get(id, key.toString());
        }
    
        //mybatis保留方法
        @Override
        public Object removeObject(Object key) {
            return null;
        }
    
        //清空缓存,在增删改时会自动调用
        @Override
        public void clear() {
            getRedisTemplate().delete(id);
        }
    
        @Override
        public int getSize() {
            return getRedisTemplate().opsForHash().size(id).intValue();
        }
    
        @Override
        public ReadWriteLock getReadWriteLock() {
            return this.readWriteLock;
        }
    
        //获取RedisTemplate,不能通过注入的方式,原因是此类是由mybatis实例化的
        private RedisTemplate getRedisTemplate() {
            //从上下文中获取redisTemplate
            RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");
            //设置key是string类型的序列
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            //设置hashKey是string类型的序列
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            return redisTemplate;
        }
    }

    在这个类中,分别重写了缓存设置、获取和删除的方法,把数据放到redis中。但是在此类中无法直接注入RedisTemplate,此类是由mybatis实例化的,不是由工厂实例化的。但是可以通过applicationContext来获取。

    4)开启缓存

    在UserDao接口上添加注解,指定缓存的配置类

    @CacheNamespace(implementation= MybatisPlusCache.class,eviction=MybatisPlusCache.class)
    public interface UserDao extends BaseMapper<User> {
        ...
    }

    5)测试。启动项目,第一次访问http://localhost:8080/users/list,查看控制台,会发现打印了sql的执行日志,多次访问此路径,它就从redis中获取数据了,同时可以在redis中看到此缓存信息。

     对于增删改操作,都会清空缓存。因此作为缓存的数据一般是频繁查询,很少修改的信息。

    7.2注意事项

    通过对比mybatis的缓存可以发现,这里指定缓存的配置类是在dao接口上用注解配置的,而mybatis是在xml中配置的。实际上,也可以在xml中配置,但是二者不可兼得。

    1)在dao接口中配置,那么只能缓存使用mybatis-plus查询出来的数据。也就是说,在xml中编写的查询语句所查询的结果是不会存入缓存的。

    2)在xml中配置,那么只能缓存xml中编写的查询语句所查询的结果,使用mybatis-plus查询出来的数据是不会存入缓存的。

    xml中配置如下:

     <cache type="com.zys.mybatisplusdemo.config.MybatisPlusCache"/>

    说明:使用mybatis-plus查询出来的数据指的是不编写sql,直接调用其内部已经编写好的查询方法。

    8.@TableField注解详细说明

    8.1说明

    属性名 描述
    value 映射数据库的字段名
    update 预处理set进行自定义注入(结合fill)
    condition  预处理where进行自定义条件查询(不常用)
    exist 是否映射数据库的字段(默认是true,值为false则不映射)
    fill 字段填充,需结合FieldFill使用

    对于value和exist在前面已经介绍,在此不再赘述。

    8.2 update-修改时操作

    1)注入当前的时间

    假如在每次更新数据时都需要把时间改成当前操作的时间,那么可以对其进行配置为数据库的时间:

    @TableField(value = "update_time", update = "now()",fill = FieldFill.UPDATE)
    private Date updateTime;

    需要结合fill使用,将其设置为更新时更新数据。设置后需调用mybatisplus自带的修改方法update(),否则不生效

    输入的SQL如下:

    UPDATE 表 SET update_time=now() WHERE 条件

    2)修改变量的值

    在每次修改时需要记录修改次数时,可以使用下面的方式。

    @TableField(value = "count",update = "%s+1", fill = FieldFill.UPDATE)
    private Integer count;

    其中"%s"是填充的字段,在这里是count,输出的SQL如下:

    UPDATE 表 SET count=count+1 WHERE 条件

    不过需要注意的是,在使用时,count在数据库中必须有值,为空时不会修改其值。

    8.3 fill与FieldFill

    对数据进行自动填充操作。上一小节结合update属性进行了说明。本小节不结合update属性进行添加或修改。

    若需要在添加时插入添加时间,修改时同步修改时间。可对对象的字段进行设置,使用fill:

    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;
    
    @TableField(value = "update_time", fill = FieldFill.UPDATE)
    private Date updateTime;

    还需要添加一个配置类实现MetaObjectHandler接口,重写两个方法

    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.Date;
    
    @Configuration
    public class MyMetaObjectHandler implements MetaObjectHandler {
    
        @Override
        public void insertFill(MetaObject metaObject) {
            this.setFieldValByName("createTime", new Date(), metaObject);
        }
    
        @Override
        public void updateFill(MetaObject metaObject) {
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
    }

    可以看出在配置类中对方法重写时,指定了字段名和时间,从而实现自定义插入时间。其他的公共字段也可以使用这种方式。

    这种方式显而易见有很大的局限性,对时间的两个字段进行了限定,那么对象的这两个字段就固定了。可根据实际需求选择是否使用这种方式。

    就是这么简单,你学废了吗?感觉有用的话,给笔者点个赞吧 !
  • 相关阅读:
    P1169 [ZJOI2007]棋盘制作[悬线法/二维dp]
    P2279 [HNOI2003]消防局的设立[树形dp]
    Django项目部署
    Python3编译安装以及创建虚拟运行环境
    ASA与N6K对接
    Django使用admin管理后台管理数据库表
    WebStrom配置
    H3C常用配置和命令
    VPC配置介绍
    Linux下编译安装MySQL
  • 原文地址:https://www.cnblogs.com/zys2019/p/12904848.html
Copyright © 2011-2022 走看看