MyBatis Plus Invalid bound statement 终极解决方案

news2024/11/17 15:56:21

MyBatis Plus Invalid bound statement 终极解决方案

    • 一、项目
      • 1.1 编码部分
        • 1.1.1 实体类
        • 1.1.2 dao层
        • 1.1.3 mapper.xml
      • 1.2 环境配置
      • 1.3 问题描述
    • 二、解决方案
      • 2.1 手动指定mapper.xml资源路径匹配规则
      • 2.2 使用mybatis自动配置
      • 2.3 测试效果
    • 三、附件

一、项目

1.1 编码部分

1.1.1 实体类

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.util.Date;

@Data
public class Student {
    @TableId
    private Integer studentId;

    private String name;

    private Integer age;

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    /**
     * 乐观锁实现注解
     * */
    @Version
    private int version;

    @TableField(exist = false)
    private long serializeId = 156612311187754L;

    @TableLogic(value = "0", delval = "1")
    private int deleted;
}
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class PageQuery {
    private int pageIndex;
    private int pageSize;
}

1.1.2 dao层

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.batis.plus.demo.entity.Customer;

public interface CustomerDao extends BaseMapper<Customer> {
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.batis.plus.demo.entity.PageQuery;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface StudentDao extends BaseMapper<Student> {
    List<Student> getStudentList(PageQuery pageQuery);
    List<Student> getStudentListLessThanAge(@Param("age") Integer age);
    List<Student> getStudentListBigThanAge(@Param("age") Integer age);
    Student getStudentByCondition(Integer age, String name);
    Student getStudentByMapCondition(Map<String, Object>  queryParam);
}

1.1.3 mapper.xml

Customer.xml内容如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.batis.plus.demo.dao.CustomerDao"></mapper>

Student.xml内容如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.batis.plus.demo.dao.StudentDao">

    <select id="getStudentList" resultType="com.batis.plus.demo.entity.Student" parameterType="com.batis.plus.demo.entity.PageQuery">
        select * from student limit #{pageIndex}, #{pageSize};
    </select>

    <select id="getStudentListLessThanAge" resultType="com.batis.plus.demo.entity.Student" parameterType="java.lang.Integer">
        select * from student where age &lt;= #{age};
    </select>

    <select id="getStudentListBigThanAge" resultType="com.batis.plus.demo.entity.Student" parameterType="java.lang.Integer">
        select * from student where age &gt;= #{age};
    </select>

    <!-- 按照参数数据传入,超过3个参数不建议使用此方式 -->
    <select id="getStudentByCondition" resultType="com.batis.plus.demo.entity.Student">
        select * from student where age = #{param1} and name = #{param2};
    </select>

	<!-- 直接使用map中的key来作为参数 -->
    <select id="getStudentByMapCondition" resultType="com.batis.plus.demo.entity.Student">
        select * from student where age = #{age} and name = #{name};
    </select>
</mapper>

1.2 环境配置

  • Application上添加了Mapper扫码配置 @MapperScan("com.batis.plus.demo.dao"), 也添加了数据源配置.
@SpringBootApplication
@MapperScan("com.batis.plus.demo.dao")
public class BatisPlusDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(BatisPlusDemoApplication.class, args);
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Autowired @Qualifier("dataSource") DataSource dataSource) throws Exception {

        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        //获取mybatis-plus全局配置
        GlobalConfig globalConfig = GlobalConfigUtils.defaults();
        //mybatis-plus全局配置设置元数据对象处理器为自己实现的类
        globalConfig.setMetaObjectHandler(new MyMetaObjectHandler());
        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
        //mybatisSqlSessionFactoryBean关联设置全局配置
        mybatisSqlSessionFactoryBean.setGlobalConfig(globalConfig);

        Interceptor[] interceptors = {paginationInterceptor()};
        mybatisSqlSessionFactoryBean.setPlugins(interceptors);

        return mybatisSqlSessionFactoryBean.getObject();
    }

    /**
     * 注册插件
     */
    @Bean
    public MybatisPlusInterceptor paginationInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor();
        // 设置请求的页面大于最大页后操作,true调回到首页,false继续请求。默认false
        pageInterceptor.setOverflow(false);
        // 单页分页条数限制,默认无限制
        pageInterceptor.setMaxLimit(100L);
        // 设置数据库类型
        pageInterceptor.setDbType(DbType.MYSQL);

        // 添加分页拦截器
        interceptor.addInnerInterceptor(pageInterceptor);

        // 添加乐观锁配置
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}
  • yml配置文件中也手动指定了mapper.xml文件路径
#配置日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mapper/*.xml
  • 项目结构也正常
    在这里插入图片描述

1.3 问题描述

@Test
void getStudent() {
    System.out.println("*********************************");
    studentListPrintln(studentDao.getStudentList(new PageQuery(1, 3)));

    System.out.println("*********************************");
    studentListPrintln(studentDao.getStudentListLessThanAge(30));

    System.out.println("*********************************");
    studentListPrintln(studentDao.getStudentListBigThanAge(30));

    System.out.println("*********************************");
    System.out.println(studentDao.getStudentByCondition(42, "李丽"));

    System.out.println("*********************************");
    Map<String, Object> param = new HashMap<>();
    param.put("name", "李丽");
    param.put("age", 45);
    System.out.println(studentDao.getStudentByMapCondition(param));
}

void studentListPrintln(List<Student> studentList) {
    if(null == studentList || studentList.isEmpty()) {
        println("没有查找到符合条件的用户");
        return;
    }

    for (Student student : studentList) {
        println(student.toString());
    }
}

然后运行提示org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.batis.plus.demo.dao.StudentDao.getStudentList, 按照常规的方式排查没有任何问题也没有任何效果。

二、解决方案

2.1 手动指定mapper.xml资源路径匹配规则

sqlSessionFactory方法中添加如下代码

// 如果使用自定义xml来进行复杂的自定义sql操作,就需要手动配置xml资源文件路径地址,否则会出现"Invalid bound statement"的报错
mybatisSqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().
                getResources("classpath:mapper/*.xml"));

2.2 使用mybatis自动配置

注释掉上面的SqlSessionFactory 手动配置代码,然后添加如下依赖

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-autoconfigure</artifactId>
    <version>1.3.2</version>
</dependency>

2.3 测试效果

*********************************
Student(studentId=1, name=李丽, age=15, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:39:41 CST 2022, version=1, serializeId=156612311187754, deleted=0)
Student(studentId=2, name=于荣光, age=66, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:40:04 CST 2022, version=1, serializeId=156612311187754, deleted=0)
Student(studentId=3, name=, age=28, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:43:34 CST 2022, version=1, serializeId=156612311187754, deleted=0)

*********************************
Student(studentId=0, name=刘韬, age=24, createTime=Tue Dec 27 17:50:05 CST 2022, updateTime=Tue Dec 27 17:50:05 CST 2022, version=0, serializeId=156612311187754, deleted=0)
Student(studentId=1, name=李丽, age=15, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:39:41 CST 2022, version=1, serializeId=156612311187754, deleted=0)
Student(studentId=3, name=, age=28, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:43:34 CST 2022, version=1, serializeId=156612311187754, deleted=0)
Student(studentId=7, name=于里昂1122, age=21, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Tue Dec 20 13:42:03 CST 2022, version=3, serializeId=156612311187754, deleted=0)
Student(studentId=8, name=于里昂2022, age=29, createTime=Tue Dec 20 09:25:36 CST 2022, updateTime=Tue Dec 20 09:25:36 CST 2022, version=2, serializeId=156612311187754, deleted=0)

*********************************
Student(studentId=2, name=于荣光, age=66, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:40:04 CST 2022, version=1, serializeId=156612311187754, deleted=0)
Student(studentId=4, name=null, age=35, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:39:30 CST 2022, version=1, serializeId=156612311187754, deleted=0)
Student(studentId=5, name=李丽, age=42, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:39:31 CST 2022, version=1, serializeId=156612311187754, deleted=1)
Student(studentId=6, name=李丽, age=45, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:39:35 CST 2022, version=1, serializeId=156612311187754, deleted=1)

*********************************
Student(studentId=5, name=李丽, age=42, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:39:31 CST 2022, version=1, serializeId=156612311187754, deleted=1)

*********************************
Student(studentId=6, name=李丽, age=45, createTime=Sat Oct 01 14:26:33 CST 2022, updateTime=Mon Dec 19 18:39:35 CST 2022, version=1, serializeId=156612311187754, deleted=1)

三、附件

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `student_id` int(11) NOT NULL COMMENT '学生ID',
  `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '姓名',
  `age` int(11) NOT NULL COMMENT '年龄',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '最后一次更新时间',
  `deleted` int(1) NOT NULL DEFAULT 0 COMMENT '是否已删除 0 未删除 1 已删除',
  `version` int(11) NOT NULL DEFAULT 1 COMMENT '版本号',
  PRIMARY KEY (`student_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (0, '刘韬', 24, '2022-12-27 17:50:05', '2022-12-27 17:50:05', 0, 0);
INSERT INTO `student` VALUES (1, '李丽', 15, '2022-10-01 14:26:33', '2022-12-19 18:39:41', 0, 1);
INSERT INTO `student` VALUES (2, '于荣光', 66, '2022-10-01 14:26:33', '2022-12-19 18:40:04', 0, 1);
INSERT INTO `student` VALUES (3, '陈', 28, '2022-10-01 14:26:33', '2022-12-19 18:43:34', 0, 1);
INSERT INTO `student` VALUES (4, NULL, 35, '2022-10-01 14:26:33', '2022-12-19 18:39:30', 0, 1);
INSERT INTO `student` VALUES (5, '李丽', 42, '2022-10-01 14:26:33', '2022-12-19 18:39:31', 1, 1);
INSERT INTO `student` VALUES (6, '李丽', 45, '2022-10-01 14:26:33', '2022-12-19 18:39:35', 1, 1);
INSERT INTO `student` VALUES (7, '于里昂1122', 21, '2022-10-01 14:26:33', '2022-12-20 13:42:03', 0, 3);
INSERT INTO `student` VALUES (8, '于里昂2022', 29, '2022-12-20 09:25:36', '2022-12-20 09:25:36', 0, 2);

SET FOREIGN_KEY_CHECKS = 1;

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

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

相关文章

imx6ull_SPI

SPI简介 SPI 是Motorola 公司推出的一种同步串行接口技术&#xff0c;是一种高速、全双工的同步通信总线。SPI 以主从方式工作&#xff0c;通常是有一个主设备和一个或多个从设备&#xff0c;一般SPI 需要4 根线&#xff0c;但是也可以使用三根线(单向传输) 这四根线如下&…

torch函数合集

torch.tensor() 原型&#xff1a;torch.tensor(data, dtypeNone, deviceNone, requires_gradFalse) 功能&#xff1a;其中data可以是:list,tuple,NumPy,ndarray等其他类型,torch.tensor会从data中的数据部分做拷贝(而不是直接引用),根据原始数据类型生成相应类型的torch.Tenso…

RestTemplate Java调用restful接口

目录1. GET请求相关方法&#xff08;1&#xff09;getForObject&#xff08;2&#xff09;getForEntity2. POST请求相关设置请求头和请求体&#xff1a;HttpEntity&#xff08;1&#xff09;postForLocation&#xff08;2&#xff09;postForObject&#xff08;3&#xff09;po…

pyqt实现聊天机器人

环境要求 通过调用openai接口实现聊天机器人功能&#xff0c;支持各种参数得调整&#xff0c;文章末尾有各个参数得说明 python3.9pyqt5环境安装 pip install pyqt5 pip install openai pip install pyinstaller源码如下&#xff1a; chat.py import sys from PyQt5.QtWid…

Cortex-A7中断控制器GIC

Cortex-A7中断控制器GIC 中断号 芯片内部的中断都会引起IRQ InterruptGIC将所有的中断源(最多1020个中断ID)分为三类: SPI(SharedPeripheralInterrupt)共享中断&#xff0c;外部中断都属于SPI中断 [ID32-1019]PPI(PrivatePeripheralInterrupt)私有中断 [ID16-31]SGI(Software-…

【MySQL】基础操作:登录、访问、退出和卸载

一、MySQL简介 MySQL数据库最初是由瑞典MySQL AB公司开发&#xff0c;2008年1月16号被Sun公司收购。2009年&#xff0c;SUN又被Oracle收购。MySQL是目前IT行业最流行的开放源代码的数据库管理系统&#xff0c;同时它也是一个支持多线程、高并发、多用户的关系型数据库管理系统。…

亚马逊物流仓库配送延误,美国暴风雪造成损失严重!

美国拉响暴风雪警报&#xff0c;物流配送大面积延误 去年年底&#xff0c;美国的暴风雪给卖家带来的阴影还没有散去。在这本该春暖百花开的季节&#xff0c;暴风雪天气又回到了美国&#xff0c;这次的破坏力比去年年底的有过之而无不及。 当地2月22日&#xff0c;暴风雪在美国…

环境搭建01-Ubuntu16.04如何查看显卡信息及安装NVDIA显卡驱动

1. 查看显卡型号、驱动 ubuntu-drivers devices2. 安装NVIDIA显卡驱动 &#xff08;1&#xff09;验证是否禁用nouveau lsmod | grep nouveau若有输出&#xff0c;没有禁用&#xff0c;进行以下操作禁用。 sudo gedit /etc/modprobe.d/blacklist.conf在文件末尾中添加两条&…

从一个实例配置引入Prometheus的PromQL语法

1. PromQL介绍 PromQL提供对时间序列数据进行逻辑运算、过滤、聚合的支持。应用于数据查询、可视化、告警处理 2. 基本用法 2.1 查询时间序列 点击Prometheus图标,进行查询页面。可以点击地图图标查看有哪些metrics name。输入要查询的metrics name和过滤条件,然后点击执行…

数字逻辑基础:原码、反码、补码

时间紧、不理解可以只看这里的结论 正数的原码、反码、补码相同。等于真值对应的机器码。 负数的原码等于机器码&#xff0c;反码为原码的符号位不变&#xff0c;其余各位按位取反。补码为反码1。 三种码的出现是为了解决计算问题并简化电路结构。 在原码和反码中&#xff0c;存…

C语言 入门教程||C语言 指针||C语言 字符串

C语言 指针 学习 C 语言的指针既简单又有趣。通过指针&#xff0c;可以简化一些 C 编程任务的执行&#xff0c;还有一些任务&#xff0c;如动态内存分配&#xff0c;没有指针是无法执行的。所以&#xff0c;想要成为一名优秀的 C 程序员&#xff0c;学习指针是很有必要的。 …

湖北某灌区量测水监测系统-案例分享

应用背景湖北某灌区是当地主要的粮棉油产区&#xff0c;由于运行多年&#xff0c;渠系工程老化&#xff0c;阻水现象严重&#xff0c;造成了大量水资源浪费。该灌区2019年对渠道进行疏挖、清淤、衬砌&#xff0c;解决输水不畅等问题&#xff0c;2022年启动灌区续建配套与节水改…

Netty核心功能以及线程模型

目录 Netty核心功能以及线程模型 Netty初探 Netty的使用场景&#xff1a; Netty通讯示例 Netty线程模型 Netty模块组件 Netty核心功能以及线程模型 Netty初探 NIO 的类库和 API 繁杂&#xff0c; 使用麻烦&#xff1a; 需要熟练掌握Selector、 ServerSocketChannel、 So…

wepack4配置入门

一、 webpack 简介 1.1 webpack 是什么 webpack是一种前端资源构建工具&#xff0c;一个静态模块打包器(module bundler)。 在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。 它将根据模块的依赖关系进行静态分析&#xff0c;打包生成对应的…

机器学习100天(三十二):032 KD树的构造和搜索

机器学习100天,今天讲的是:KD树的构造和搜索! 《机器学习100天》完整目录:目录 在 K 近邻算法中,我们计算测试样本与所有训练样本的距离,类似于穷举法。如果数据量少的时候,算法运行时间没有大的影响,但是如果数据量很大,那么算法运行的时间就会很长。这在实际的应用…

GFD563A101 3BHE046836R0101

GFD563A101 3BHE046836R0101关于高端涂布机张力控制系统方案的介绍高端涂布机张力控制系统方案涂布机是将具有某种功效的胶&#xff0c;或者油墨类物质均匀粘连在塑料薄膜、铝箔、纺织品等表面的机械设备。本系统从放卷到收卷共采用七台变频器&#xff0c;其中收放卷采用闭环张…

Databend 开源周报第 81 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.com 。Whats New探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。Accepted RFCsrfc: 查询结果缓存…

Cartesi 举办的2023 黑客马拉松

Cartesi 是具有 Linux 运行时的特定于应用程序的Rollups执行层。Cartesi 的特定应用程序 Optimistic Rollup 框架使区块链堆栈足够强大&#xff0c;开发人员可以构建计算密集型和以前不可能的去中心化实例。Cartesi 的 RISC-V 虚拟机支持 Linux 运行时环境&#xff0c;允许像你…

DevOps 学习笔记(二)| 使用 Harbor

文章目录1. 上传镜像到 Harbor2. 拉取 Harbor 镜像3. 使用 Jenkins 操作 Harbor1. 上传镜像到 Harbor 首先在CI/CD 服务器中配置 Docker mkdir -p /etc/docker/ cd /etc/docker/ vim daemon.json其中的 IP 地址为Harbor 服务器的 IP 地址 {"xxx": "xxxx"…

IGH主站通信测试csp模式(DC同步 preemrt)连通一从站并实现控制

IGH主站通信测试 linuxcnc配置基础机器人控制LinuxCNC与EtherCAT介绍&&PDO&SDO&#xff0c;搭建环境步骤 需要配置IGH主站的查看这篇文章 linux系统学习笔记7——一次性安装igh-ethercat主站 CSP模式 DC同步方式 preemrt实时补丁 直接上代码&#xff0c;这…