MytatisP详解

news2025/2/28 0:27:00

MP详解

  • 一、基础使用
    • 1.引入
    • 2.Entry中的常用注解
    • 3.BaseMapper 、IService、ServiceImpl
        • 3.1BaseMapper
      • 3.2IService、ServiceImpl
    • 4.常用配置
      • 4.1 application.yml配置
      • 4.2 configuration 配置
    • 5.Wrapper
    • 6.分页
      • 6.1使用分页方式一
    • 7.自定义分页:查询指定列
      • 7.1 先用MP的分页只查询出对应记录的id
      • 7.2 根据第一步查询到的id,在进行定量筛查
    • 8.多数据源
      • 8.1引入多数据源依赖
      • 8.2.applicaiton编写配置
      • 8.3使用 @DS
  • 二、代码自动生成
    • 1.引入依赖:
    • 2.编写自动生成代码
    • 3.运行展示
  • 三、Mybatis-plus的弊端
    • 1.默认分页功能不适合做大数量的分页
    • 2.默认的批量插入功能,使用的是拆解为多条insert into ,而不是使用一条insert into
    • 3.当数据库字段为空时,MP可能会报空指针
    • 4.数据库日期类型,当数据为空时会出现映射失败的情况
    • 5.当数据列为空时,结果集会自动过滤掉为空的列,返回前端时无该列
    • 6.如何写and ( a=2 or b=3) 这种条件
    • 7.如何使用MP进行连接查询
  • 四、可能的异常
    • 1.异常:InvalidDataAccessApiUsageException: Error attempting to get column 'taskPlanEndTime' from result set. Cause: java.sql.SQLFeatureNotSupportedException

一、基础使用

mybatis-plus中最常用的应该就是他的基础功能了,比如BaseMapper、IService、ServiceImpl,使用他们三个可以快速完成大部分的增删改查需求。

1.引入

启动类支持两种声明

1.使用MapperScan注解,传入Mapper接口的包名。

2.使用ComponentScan注解,同时配合Repository注解,这样也可以实现上面的功能。

增加依赖:这里只是使用BaseMapper、IService、ServiceImpl等基础信息的依赖,若是需要做自动化或者其他功能还需要增加其他依赖

 	 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>2.4.4</version>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <!--引入alibaba的json处理对象-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>

        <!--引入mybatis的依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>

        <!--引入连接mysql的驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>

        <!--引入数据源连接池依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.19</version>
        </dependency>

<!--        引入mybatisplus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

若是使用必须在Springboot启动类上增加MapperScan,这个MapperScan可以帮助我们自动寻找到Mapper接口从而生成Mapper配置文件。(这里如果不加MapperScan,也可以在每个Mapper接口上增加Mapper注解)。其实这里还涉及到怎么寻找Mapper的问题,MP默认情况下把自动生成的Mapper配置文件,放在资源目录下的mapper文件夹下,若是我们手动生成,也放到这里的面是不用增加mapper文件的配置信息的

// 启动类代码
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan(value = "com.ebbing.task.mapper")
@SpringBootApplication
public class EbbingApplication {
    public static void main(String[] args) {
        SpringApplication.run(EbbingApplication.class, args);
    }
}

2.Entry中的常用注解

上面准备好以后就可以开始编写实体类了,实体类对应数据库表。若是表名和实体类名相同,字段名和数据库字段名也相同(数据库使用下划线,实体使用驼峰是支持自动转换的,也认为相同),且主键id就是id,则我们无需任何处理,MP可以全部帮我们进行自动对其。但有任何不同我们是都需要使用注解进行声明的。

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * <p>
 * 
 * </p>
 *
 * @author pcc
 * @since 2023-08-04
 */
@Data
@TableName("tb_task")
@Accessors(chain = true)
public class TbTask implements Serializable {

    private static final long serialVersionUID = 1L;

      /**
     * 主键
     */
      @TableId(value = "task_id", type = IdType.AUTO)
      private Long taskId;

      /**
     * 任务名
     */
      private String taskName;

      /**
     * 任务描述
     */
      private String taskDesc;

      /**
     * 任务文档链接
     */
      private String taskLinkText;

      /**
     * 任务脑图连接
     */
      private String taskLinkMap;

      /**
     * 任务关键程度: 1 普通,2重要,3很重要,4非常重要
     */
      private Integer deep;

      /**
     * 创建时间
     */
      private LocalDateTime createTime;

      /**
     * 创建人
     */
      private String createBy;

      /**
     * 修改时间
     */
      private LocalDateTime updateTime;

      /**
     * 修改人
     */
      private String updateBy;

      /**
     * 状态:0:正常,1删除
     */
      @TableLogic
      private Integer isDeleted;

      /**
     * 数据版本:乐观锁
     */
      @Version
      private Integer version;

}

上面是自动生成的实体类,当然和我们手动写没有太大区别,总结下其中的注解

  • 注解@TableName
    主要用以声明实体对应的表,此外还支持前缀等其他声明,不过基本只使用用来和表作对应,当表明和实体类名不一致时需要使用该注解,需要特别注意的是,实体类的驼峰和表名的下划线是无法完成映射的,这点和字段与属性的对应有区别。

  • 注解@TableId
    value用以声明主键是哪个字段,type用以声明主键的生成规则,默认是无,也就是不填充,总共支持五种规则:①IdType.AUTO: 自增注解,对应数据库的auto_increment,②IdType.NONE:这是默认的行为,应该是需要自己去操作的。③IdType.INPUT:需要自己输入主键,若是插入时没有会报错,④IdType.ASSIGN-ID:这是雪花算法生成的id,可以用来做分布式服务的主键策略,他是支持的。**⑤IdType.**ASSIGN_UUID:这里使用UUID做为主键,这个不是一个好的选择,UUID对于数据库的BTREE索引来说不够高效,范围查询效率很低。

  • 注解@TableField
    这个注解使用率也是特别高的,主要用来声明属性和列的对应关系,若只是驼峰和下划线的区别则无需声明,若是该字段无需与数据库进行映射,可以将

    • exists=false,来禁止数据库的映射

    • select = false若是该字段永远不想要被select查询到,可以使用select = false

    • updateStrategy=FieldStrategy.DEFAULT 这是默认值,当执行更新策略时忽略null的场景他和NOTNULL等效,也就是说传递null不更新,如果想要更新可以更改为FieldStrategy.IGNORED意思为忽略判断直接更新,此时为null和为空都会更新,当然还有别的选择可以根据非null更新,非空更新等。

    • insertStrategy=FieldStrategy.DEFAULT,这个和上面没有区别,只不过是应用插入场景。

    • fill=FieldFill.DEFAULT 默认是不处理,如果改为FieldFill.INSERT 即表示新增时必须有值,不然报错,相当于断言,此外还有别的支持具体看源码吧

      他除了value、exists、select,其他支持的功能比较多,不过基本用不到,这里不一一列举了

  • 注解@TableLogic:
    (0在使用,1已删除)这个注解被使用与逻辑删除字段上,若是遵循驼峰转下划线的规则,则无需多余声明什么,只需增加该注解在对应字段上即可。增加该注解有一个前提:数据库有该字段,且默认值为0。他有两个作用:①当增加了该注解后,调用BaseMapper的delete方法或者IService的remove方法,他们都不会去真正删除记录,而是将对应记录的逻辑删除字段更改为1.②当增加了该注解后无论是BaseMapper还是IService的查询方法默认都会增加逻辑删除字段等于0的条件。

  • 注解@Version:
    这个注解是用来声明乐观锁的注解,乐观锁即CAS:比较然后交换。使用它有一个前提条件,就是我们需要手动增加支持乐观锁的配置,如下:

    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author pcc
     */
    @Configuration
    public class MPConfig {
    
        @Bean
        public MybatisPlusInterceptor getInstance(){
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return interceptor;
        }
    }
    

增加了上面的配置后,MP为自动拦截我们的sql,并为我们增加乐观锁的支持了,分页其实也需要这个,都是一个原理。然后就是@Version 有两个作用和一个注意点

*   1.增加乐观锁以后,若是我们没有传递这个信息到MP,那默认是不适用乐观锁的,所以若是使用,则必须保证前后端交互时这个字段必须传递。
*   2.只需要增加一个配置和一个注解,即可使用乐观锁,在更新数据库时,MP为自动增加乐观锁的条件,比如verison=0,满足才会更新
*   3.每次更新记录,乐观锁的值都会+1.
*   4.需要特别注意的是,乐观锁和数据版本不可混为一谈,数据版本一般只有审核流程通过才会+1,乐观锁纯粹是为了防止数据更新时出现错误而设置的,如需数据版本应从新声明。

3.BaseMapper 、IService、ServiceImpl

这三个才是MP的核心啊,只要掌握了他们三个,大部分的CRUD就都解决了。

3.1BaseMapper

有时候我们甚至直接使用BaseMapper都是可以的,因为这里已经包含了大部分我们需要的方法,直接使用他可以满足大部分的功能,不过有些需要业务处理的场景,我们还是需要写Service的。

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ebbing.task.entity.TbDict;

/**
 * <p>
 *  Mapper 接口
 * </p>
 *
 * @author pcc
 * @since 2023-08-04
 */
public interface TbDictMapper extends BaseMapper<TbDict> {
}

如上所示,当我们想要写一个Mapper接口时,只需要继承BaseMapper,同时声明BaseMapper的泛型类,这样我们大部分的CRUD的方法都不用写了,MP利用这个泛型类,通过反射来为我们在resource下的mapper文件夹中自动生成了Mapper的配置文件(mvn install后可以看到).这里有一个需要注意的点是:若是不在当前接口增加Mapper注解,则需要在启动类上增加MapperScan注解,同时将Mapper接口所在的文件夹进行声明,后面我们就可以直接通过autowired来进行使用这个Mapper了

3.2IService、ServiceImpl

IService是Mp提供的接口,里面同样包含了很多CRUD的方法,但是他是一个接口,所以我们不可能直接使用的,所以必须配合ServiceImpl才可以使用,ServiceImpl里面正常IService的实现类,不过ServiceImpl里面大部分方法还是调用的是BaseMapper的实现,所以ServiceImpl声明时,我们还需要传入BaseMapper的实现,也就是我们自己写的Mapper接口了。

import com.ebbing.task.entity.TbTask;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author pcc
 * @since 2023-08-04
 */
public interface ITbTaskService extends IService<TbTask> {
}
import com.ebbing.task.entity.TbTask;
import com.ebbing.task.mapper.TbTaskMapper;
import com.ebbing.task.service.ITbTaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author pcc
 * @since 2023-08-04
 */
@Service
public class TbTaskServiceImpl extends ServiceImpl<TbTaskMapper, TbTask> implements ITbTaskService {
}

需要特別注意的是无论是IService还是ServiceImpl都是需要声明泛型的,且ServiceImpl是类需要去继承,而不是实现,这样就完成了所有的接口开发了,剩下我们自己写Controller就行了。

4.常用配置

4.1 application.yml配置

mybatis-plus:
  # 配置Mybatis的配置文件位置,这个基本用不到,现在都是在application中配置
#  config-location: classpath:mybatis-config.xml
  # 下面是默认配置,如果放了下面的位置,则无需增加该配置
  mapper-locations: classpath:mapper/**/*.xml
  # 这个没有默认,别名包扫描,需要直接配即可
  type-aliases-package: com.ebbing.task.entity
  configuration:
    # 默认值是true
    call-setters-on-nulls: true
    # 默认开启缓存,这个是二级缓存
    cache-enabled: true
    # 开启控制台日志打印
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    # 这个是和注解@TableLogic配合使用的,设置后删除数据会将逻辑删除字段设置为1
    logic-delete-value: 1
    # 这个是和注解@TableLogic配合使用的,设置后新增数据会将逻辑删除字段设置为0,且查询时会默认携带删除字段为0的条件
    logic-not-delete-value: 0
    db-config:
      # 设置表名前缀,这个在实体类中使用,若是所有的表都有共同前缀,使用这个很方便
#      table-prefix: tb_
      # 这个配置是设置ID自增类型的,一般使用AUTO或者ASSIGN_ID
      id-type: auto

4.2 configuration 配置

这里一般就是需要配置分页插件和乐观锁插件,因为他们都需要使用拦截器对sql执行进行拦截,然后更改sql

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author pcc
 */
@Configuration
public class MPConfig {

    @Bean
    public MybatisPlusInterceptor getInstance(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 拦截sql,实现分页
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 拦截sql,实现乐观锁
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

5.Wrapper

Wrapper也算是MP的一个核心类,因为大部分的查询条件都是使用Wrapper来进行拼接的,而我们上面使用的BaseMapper、IService中很多都是传入Wrapper或者Wrapper的实现类,比如

Long selectCount(@Param("ew") Wrapper<T> queryWrapper);

List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);

从上面可以看出,只要是Wrapper我们都是可以传入的,需要特别注意泛型别漏了。

在这里插入图片描述
一般使用LambdaQueryWrapper比较多一些,因为书写简单,注意之类使用时不能忘了泛型。

6.分页

使用MP的分页功能无需导入多余的依赖,只需要配置下对Mybatis的sql进行拦截即可。这块代码上面其实也列过了

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author pcc
 */
@Configuration
public class MPConfig {

    @Bean
    public MybatisPlusInterceptor getInstance(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 拦截sql,实现分页
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 拦截sql,实现乐观锁
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

6.1使用分页方式一

在查询时直接传入page,和Wrapper,这样我们查询的分页结果会直接封装到Page里面,若是不需要对数据结构进行更改,可以直接返回。

    @PostMapping("/getTaskItems")
    public IPage<TbTaskItems> getTaskItems(TbTaskItemsVO tbTaskItemsVO){
        Page<TbTaskItems> page = new Page<>();
        page.setCurrent(tbTaskItemsVO.getPageIndex());
        page.setSize(tbTaskItemsVO.getPageSize());
        iTbTaskItemsService.page(page,null);
        return page;
    }

7.自定义分页:查询指定列

当数据列特别大时,比如上千万的表,越往后分页就会越久,倘若使用mybatis-plus提供的分页,很有可能数据会查不出来。完全可以分两步走:

7.1 先用MP的分页只查询出对应记录的id

因为id是聚簇索引不需要回表,效率会非常的高,这样可以快速帮我们定位到记录。那Mybatis-plus怎么做到只查询指定列呢?

这里实现方式很多,最方便的就是使用Wrapper来进行直接限定查询到得列:

    @PostMapping("/getTaskItems")
    public IPage<TbTaskItems> getTaskItems(TbTaskItemsVO tbTaskItemsVO){
        Page<TbTaskItems> page = new Page<>();
        page.setCurrent(tbTaskItemsVO.getPageIndex());
        page.setSize(tbTaskItemsVO.getPageSize());

        iTbTaskItemsService.page(page,
                new LambdaQueryWrapper<TbTaskItems>().select(
                        TbTaskItems::getTaskId,
                        TbTaskItems::getItemReviewTime,
                        TbTaskItems::getVersion)
                );
        return page;
    }

7.2 根据第一步查询到的id,在进行定量筛查

看起来多了一步,其实在数据量大时会提升非常多的性能,这也是大部分大数量时分页的一种方案

8.多数据源

适合读写分离时使用,使用起来也很简单:

8.1引入多数据源依赖

版本和MP保持一致即可

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

8.2.applicaiton编写配置

区别就是相比于一个数据源,多配置了一遍而已,这里的primary是配置默认数据源的,当不在使用时指定就使用该配置指定的数据源,strict配置false,默认也是false,是否强制校验数据源,强制的话数据源一旦出错就会报错,而不会使用默认的数据源

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #是否强制校验数据源
      datasource:
        master:
          type: com.alibaba.druid.pool.DruidDataSource
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://192.168.150.180:3306/ebbing?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
          username: root
          password: super
        slave:
          type: com.alibaba.druid.pool.DruidDataSource
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://192.168.150.180:3306/ebbing2?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
          username: root
          password: super

8.3使用 @DS

使用时也很简单,直接在对应的Service的实现类或者方法上增加该注解即可,该注解只有一个属性value,声明为我们的master或者slave,就可以正常调用对应的数据源了。

二、代码自动生成

代码生成配置很简单,不过内置的是mysql5的驱动,支持5.5.45+, 5.6.26+ and 5.7.6+ ,若是换驱动还得其他配置。默认情况下,我们只需要声明url、username、password即可。

1.引入依赖:

<!-- 引入mybatis-plus依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>

<!-- 引入代码自动生成依赖,这个依赖必须单独引 -->
<dependency                
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.1</version>
</dependency>
<!-- 官网上没说需要引入这个依赖,但是我自己测试时,缺少这个依赖运行不了,也有可能是多级依赖下载失败了 -->
<dependency>    
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>

当时引入velocity时,下面的包一直进不来,所以单独引了下面的包,但是其实可以不引,因为下面的包,是上面包的依赖包,会被加载,若是加载不出来,则需要我们手动去引入

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>

2.编写自动生成代码

下面是代码,我们只声明了数据库的配置信息,然后采用交互式输入作者和包名路径即可,这里的包名路径记得一定得是我们项目里的实际的包名路径,比如我的项目的根路径是com.example.demo5,我想要自动生成的代码新开一个包叫task,那我们输入包名时就应该这么写:com.example.demo5.task。后面自动生成的代码路径都是这个了:

package com.example.demo5.generage;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import java.sql.SQLException;

/**
 * <p>
 * 快速生成
 * </p>
 *
 * @author pcc
 * @since 2023-08-04
 */
public class FastAutoGeneratorTest {
     static final String URL = "jdbc:mysql://192.168.150.180:3306/ebbing";
     static final String USERNAME = "root";
     static final String PASSWORD = "super";

    /**
     * 执行 run
     */
    public static void main(String[] args) throws SQLException {
        FastAutoGenerator.create(
                //配置数据源
                new DataSourceConfig.Builder(URL, USERNAME, PASSWORD))
                // 全局配置: 注意包名需要使用全路径
                .globalConfig((scanner, builder) -> builder.author(scanner.apply("请输入作者名称?")).fileOverride())
                // 包配置
                .packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?")))
                // 策略配置:内部声明表名
                .strategyConfig(builder -> builder.addInclude("tb_task"))
                .execute();
    }
}

3.运行展示

下面是运行成功的截图:

已连接到目标 VM, 地址: ''127.0.0.1:5332',传输: '套接字''
请输入作者名称?
pcc
请输入包名?
com.example.demo5.task
11:51:38.854 [main] DEBUG com.baomidou.mybatisplus.generator.AutoGenerator - ==========================准备生成文件...==========================
Fri Aug 04 11:51:39 CST 2023 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
11:51:39.529 [main] DEBUG com.baomidou.mybatisplus.generator.config.querys.MySqlQuery - 执行SQL:show table status WHERE 1=1  AND NAME IN ('tb_task')
11:51:39.545 [main] DEBUG com.baomidou.mybatisplus.generator.config.querys.MySqlQuery - 返回记录数:1,耗时(ms):14
11:51:39.563 [main] DEBUG com.baomidou.mybatisplus.generator.config.querys.MySqlQuery - 执行SQL:show full fields from `tb_task`
11:51:39.578 [main] DEBUG com.baomidou.mybatisplus.generator.config.querys.MySqlQuery - 返回记录数:11,耗时(ms):14
11:51:39.603 [main] DEBUG org.apache.velocity - CommonsLogLogChute name is 'org.apache.velocity'
11:51:39.604 [main] DEBUG org.apache.velocity - Initializing Velocity, Calling init()...
11:51:39.604 [main] DEBUG org.apache.velocity - Starting Apache Velocity v1.7 (compiled: 2010-11-19 12:14:37)
11:51:39.604 [main] DEBUG org.apache.velocity - Default Properties File: org\apache\velocity\runtime\defaults\velocity.properties

这里只展示了部分的执行成功信息,默认情况下代码会生成在D盘下面的我们声明的路径中。

三、Mybatis-plus的弊端

1.默认分页功能不适合做大数量的分页

在第一章第7节,已说过该部分

2.默认的批量插入功能,使用的是拆解为多条insert into ,而不是使用一条insert into

如果需要考虑到效率,这种需要自己写批量新增的功能,如果表数据量比较大,最好是自己写批量新增的功能,而不是使用mybatis-plus来使用他的批量新增功能

3.当数据库字段为空时,MP可能会报空指针

这里原因是因为,默认(3.5.1)情况下查询的值即使为null也会将值set到对应的实体中,若是想要禁止这种情况,有两种方案。

①:在字段上增加注解@TableField(exist=false),这样当这个配置是忽略这个字段与数据库的映射
②:全局配置增加mybatis-plus.configuration.call-setters-on-nulls=false,这是为全局的字段增加这个配置,试了不好使

4.数据库日期类型,当数据为空时会出现映射失败的情况

核心问题应该还是数据源的问题,也看到了这部分问题的解释。
解决的方法有以下几种:
1.增加针对LocalDateTime的序列化操作,试了不好使
2.更换druid数据源,试了不好使
3.升级druid,升级出现问题,操作中断
4.数据库字段使用date代替datetime,对应java里的LocalDate,试了不好使
5.增加某个jar,说是解决这个问题,试了不好使
6.取消数据库字段datetime,使用了String,最后实在没办法,用了下下策

5.当数据列为空时,结果集会自动过滤掉为空的列,返回前端时无该列

这个问题解决办法:

①。配置mybatis-plus的配置:

mybatis-plus:
  configuration:
    # 默认值是true,即:即使查询的值为null,也会进行set,这会导致空指针,所以改为false
    call-setters-on-nulls: true

②或者使用mybatis的配置,也是这个配置

mybatis:
  configuration:
    call-setters-on-nulls: true

③若是以上都不行,建议换个http客户端工具:我的就是工具问题,找了半天,换了个工具正常了,离了大浦

6.如何写and ( a=2 or b=3) 这种条件

如下:
wrapper.and(i -> i.eq(T::getA, 2).or().eq(T::getB, 3));
and()方法接收一个函数式接口作为参数,在函数里我们可以写出一个完整的条件表达式。
示例中我们写了:

  • i.eq(T::getA, 2) 表示 a = 2
  • i.or() 表示或条件
  • i.eq(T::getB, 3) 表示 b = 3
    将这些条件通过or()组合起来,就可以表达一个and (a = 2 or b = 3)的条件。
    and()方法会将这整个条件表达式作为一个单元进行组合。

7.如何使用MP进行连接查询

以下方法3.4.2才开始支持

wrapper.innerjoin(右表字段,左表字段)

wrapper.leftjoin(右表字段,左表字段)

四、可能的异常

1.异常:InvalidDataAccessApiUsageException: Error attempting to get column ‘taskPlanEndTime’ from result set. Cause: java.sql.SQLFeatureNotSupportedException

异常各版本:

druid:1.1.11
Mybatis-plus:3.4.1
Mysql:5.7

使用了低版本的Druid数据源。这个低版本的Druid数据源不支持JDK8中的LocalDate、LocalTime、LocalDateTime等日期类型,所以导致了异常的发生。

为了解决这个问题,你可以下载一个高于或等于1.1.21版本的Druid依赖,并将其添加到你的项目中。你可以在你的项目的pom.xml文件中添加以下依赖项:

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>

这样,你就可以使用支持JDK8日期类型的Druid数据源,从而解决InvalidDataAccessApiUsageException异常

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1087287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx绑定tomcat与tomcat联合使用的配置(nginx反向代理tomcat的配置说明)

nginx反向代理tomcat通信配置 &#xff08;内容来自网上&#xff0c;注解部分才是原创&#xff09; 切记&#xff1a; url的意思就是 unifed resource location 统一资源定位 其中location就是定位的意思 所以上文中的location就有 对应匹配的 url 标识的资源的相关配置之…

go 递归 数据多层级横向展开 插入数据库

需求&#xff0c;在两张表(一张主表&#xff0c;一张明细表&#xff0c;一对多的关系)中有层级关系&#xff0c;比如A(主表数据)&#xff0c;A1&#xff0c;A2&#xff0c;A3&#xff0c;A4(明细表数据)&#xff0c;而A1这些数据下面还有别的数据那它们也会出现在主表中&#x…

Pygame中将鼠标形状设置为图片2-2

3 编写主程序 在主程序中&#xff0c;首先创建屏幕并且完成一些准备工作&#xff0c;之后在while循环中不断更新sprite实例即可。 3.1 创建屏幕及准备工作 创建屏幕及准备工作的代码如图5所示。 图5 创建屏幕及准备工作 其中&#xff0c;第20行代码调用pygame.mouse模块中的…

足球公平盘、实力盘和盘口合理性的模型探讨

1. 公平盘模型事件 9月份&#xff0c;突然间好多人加我vx问及公平盘模型能否依靠下图做出来&#xff0c;几年没有人提及公平盘&#xff0c;突然好多人这么一问应该是从同一个讨论群过来的。 1.1 公平盘介绍 按照字面意思&#xff1a;真实反应即将开赛的两支球队在主客场时的让…

【Spring Boot】RabbitMQ消息队列 — RabbitMQ入门

💠一名热衷于分享知识的程序员 💠乐于在CSDN上与广大开发者交流学习。 💠希望通过每一次学习,让更多读者了解我 💠也希望能结识更多志同道合的朋友。 💠将继续努力,不断提升自己的专业技能,创造更多价值。🌿欢迎来到@"衍生星球"的CSDN博文🌿 🍁本…

微服务11-Sentinel中的授权规则以及Sentinel服务规则持久化

文章目录 授权规则自定义异常结果规则持久化实现Push模式 授权规则 根据来源名称对请求进行拦截 ——>我们需要解析来源名称&#xff08;RequestOriginParser默认解析都为default&#xff09;&#xff0c;所以我们要自定义一个实现类&#xff08;根据请求头解析&#xff0c…

MIT 6.S081 Operating System/Fall 2020 macOS搭建risc-v与xv6开发调试环境

文章目录 本机配置安装环境Homebrew执行安装脚本查看安装是否成功 RISC-V tools执行brew的安装脚本 QEMUXV6 测试有用的参考链接&#xff08;感谢前辈&#xff09;写在结尾 本机配置 电脑型号&#xff1a;Apple M2 Pro 2023 操作系统&#xff1a;macOS Ventura 13.4 所以我的电…

CTFHub SSRF 题目

文章目录 CTFHub SSRF 通关教程1. 内网访问&#xff0c;伪协议利用1.1 内网访问1.2 伪协议读取文件1.3 端口扫描 2. POST请求&#xff0c;上传文件&#xff0c;FastCGI协议&#xff0c;Redis协议2.1 POST请求2.2 上传文件2.3 FastCGI协议2.4 Redis协议 3. Bypass系列3.1 URL By…

中国人民大学与加拿大女王大学金融硕士究竟适合金融国企人还是金融外企人呢?

随着中国经济的快速发展&#xff0c;金融业已经成为国民经济的重要支柱产业。在这个背景下&#xff0c;金融国企和金融外企的发展也日益繁荣。想发展不断学习的脚步是一刻不能停歇的&#xff0c;由此&#xff0c;免联考双证的中国人民大学与加拿大女王大学金融硕士就开始逐渐走…

有哪些好用的电容笔?苹果平板触控笔推荐

对于学生党来说&#xff0c;用哪种电容笔比较合适&#xff1f;苹果的原装电容笔&#xff0c;尽管性能很好&#xff0c;功能也很多&#xff0c;却就是太贵了&#xff0c;一般人根本买不起&#xff0c;而且重量还挺重&#xff0c;握在手上使用久了会很费劲。如果你只是想单纯地用…

申博|2024国内985院校申博时间参考

转眼已近10月中旬&#xff0c;小编给大家总结了2024年国内985院校博士申请预计时间汇总&#xff0c;一般各高校都是临近博士报名启动才会发布具体的招生通知&#xff0c;所以想要申博的同学们可以在日期临近前注意查看高校官方信息。 以下申请时间为2023年博士申请的时间&…

4.添加3DTiles

愿你出走半生,归来仍是少年&#xff01; 在构建好的三维场景中添加3DTile&#xff08;本地离线数据以及在线服务&#xff09;。 1.在线服务 首先需要准备一个已发布出来的3DTile服务. 打开Cesium面板&#xff0c;添加Blank 3D Tileset &#xff0c;然后选中该对象&#xff0c;…

WIFI产品使用指导说明

一、登录服务器 二、新建产品 三、设置WIFI产品的联网参数 1、恢复出厂设置 2、设置参数 四、操作更新 网络连接特性&#xff1a; 路由器掉线得情况下&#xff0c; 第一次&#xff0c;搜索网络1分钟间隔第二次&#xff0c;搜索网络1分钟间隔第三次&#xff0c;搜索网络…

git下载bos仓库代码

安装git 插件 登录git 填写仓库地址后 把仓库代码 下载某个文件夹&#xff0c; 然后再拷贝到自己的 解决方案中

开发信群发技巧有哪些?外贸邮件怎么群发?

如何做外贸开发信群发&#xff1f;外贸开发信群发用什么邮箱好&#xff1f; 无论你是一位销售专业人员&#xff0c;一名初创企业家还是一家大型公司的市场营销团队成员&#xff0c;都能受益于掌握这些技巧。下面蜂邮EDM将为您介绍一些关键的开发信群发技巧&#xff0c;帮助你在…

批量执行insert into 的脚本报2006 - MySQL server has gone away

数据库执行批量数据导入是报“2006 - MySQL server has gone away”错误&#xff0c;脚本并没有问题&#xff0c;只是insert into 的批量操作语句过长导致。 解决办法&#xff1a; Navicat ->工具 ->服务器监控->mysql ——》变量 修改max_allowed_packet大小为512…

树莓派 5添加对PCIe 2.0支持,耗时七年花费2500万美元

据了解&#xff0c;早在上个月底&#xff0c;树莓派 5就已经正式发布&#xff0c;该机主要是提升了硬件性能&#xff0c;添加了对 PCIe 2.0的支持。 树莓派 5采用了 64 位四核 Arm Cortex-A76 处理器&#xff0c;频率为 2.4GHz&#xff0c;相比上一代性能提高了 2~3倍。并配备…

LeetCode【128】最长连续序列

题目&#xff1a; 分析&#xff1a; 1、最长连续序列的长度为 y-x1&#xff0c;如1-4&#xff1a;4-11 4 2、不要被这里的On误导&#xff0c;不敢使用双层循环 3、只要找到最小的数值&#xff0c;并由此开始计算&#xff0c;不产生重复计算&#xff0c;则为On 代码&#xf…

【C++】从认识using namespace std开始进入C++的学习

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 &#x1f4e3;&#x1f4e3;&#x1f4e3;今天博主…

AI秘籍:助您提升办公和学习效率

AI产品在提升办公和学习效率上可是有一手呢&#xff01;看看下面这些实用的AI产品&#xff0c;让你分分钟变成效率达人&#xff01; 1. 语音助手&#xff1a;不论是Siri、Cortana还是小冰&#xff0c;一个简单的语音指令就能帮你执行任务&#xff0c;比如发邮件、设提醒、查资料…