mybatis竟然报”Invalid value for getInt()”

背景

使用 mybatis遇到一个非常奇葩的问题,错误如下:

Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'name' from result set.  Cause: java.sql.SQLException: Invalid value for getInt() - 'hhhh'

场景

还原一下当时的情况:

public interface UserMapper {
    @Results(value = {
            @Result(property = "id", column = "id", javaType = Long.class, jdbcType = JdbcType.BIGINT),
            @Result(property = "age", column = "age", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
            @Result(property = "name", column = "name", javaType = String.class, jdbcType = JdbcType.VARCHAR)
    })
    @Select("SELECT id, name, age FROM user WHERE id = #{id}")
    User selectUser(Long id);
}

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

public class MapperMain {
    public static void main(String[] args) throws Exception {
        MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8");

        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment = new Environment("development", transactionFactory, dataSource);
        Configuration configuration = new Configuration(environment);
        configuration.addMapper(UserMapper.class);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

        try (SqlSession session = sqlSessionFactory.openSession()) {
            UserMapper userMapper = session.getMapper(UserMapper.class);
            System.out.println(userMapper.selectUser(1L));
        }
    }
}

数据库如下:

mybatis竟然报"Invalid value for getInt()"

上面是一个很简单的例子,就是根据 id选出用户的信息,运行结果如下:

User(id=1, age=2, name=3)

没有任何问题,但是我再往数据库里插入一条数据,如下:

mybatis竟然报"Invalid value for getInt()"

MapperMain类中增加一行代码,如下:

System.out.println(userMapper.selectUser(2L));

运行结果如下:

User(id=1, age=2, name=3)
### Error querying database.  Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'name' from result set.  Cause: java.sql.SQLException: Invalid value for getInt() - 'hhhh'
......

可以看出第一条查询没有问题,第二条查询就报错了

初探

其实我的直觉告诉我,是不是因为 User类里字段顺序和 SQL语句里 select字段的顺序不一致导致的,那就来试一下吧

改一下 User类里字段的顺序:

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

结果如下:

User(id=1, name=3, age=2)
User(id=2, name=hhhh, age=3)

果不其然,直觉还是很6的

或者改一下 SQL语句里 select字段的顺序:

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

public interface UserMapper {
    @Results(value = {
            @Result(property = "id", column = "id", javaType = Long.class, jdbcType = JdbcType.BIGINT),
            @Result(property = "age", column = "age", javaType = Integer.class, jdbcType = JdbcType.INTEGER),
            @Result(property = "name", column = "name", javaType = String.class, jdbcType = JdbcType.VARCHAR)
    })
    @Select("SELECT id, age, name FROM user WHERE id = #{id}")
    User selectUser(Long id);
}

以我们的直觉,结果肯定也没问题,果不其然,如下:

User(id=1, age=2, name=3)
User(id=2, age=3, name=hhhh)

再探

其实到上一步,问题已经解决了,可以继续干活了,但是搞不懂为什么,心里总觉得不踏实。

bugdebug开始,从下面的入口开始:

mybatis竟然报"Invalid value for getInt()"

追踪到如下:

mybatis竟然报"Invalid value for getInt()"

mybatis竟然报"Invalid value for getInt()"

可以看出 User这个类是有构造函数的,而且是包含所有字段的构造函数
利用这个构造函数创建实例的时候,参数的顺序就是SQL语句选择字段的顺序,不会根据映射关系去选择
所以就出现了类型不匹配

那我们再来看一下问什么会有一个这样的构造函数产生,直觉告诉我是 @Builder这个注解

一起来看一下 User编译后的结果:

public class User {
    private Long id;
    private String name;
    private Integer age;

    User(final Long id, final String name, final Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }

    public static class UserBuilder {
        private Long id;
        private String name;
        private Integer age;

        UserBuilder() {
        }

        public User.UserBuilder id(final Long id) {
            this.id = id;
            return this;
        }

        public User.UserBuilder name(final String name) {
            this.name = name;
            return this;
        }

        public User.UserBuilder age(final Integer age) {
            this.age = age;
            return this;
        }

        public User build() {
            return new User(this.id, this.name, this.age);
        }
    }
}

果然如此, UserBuilder.build()方法就是利用这个构造函数来生成的。

结局

最终解决方案就是给 User类加上无参的构造函数就OK了,如下:

java@data @Builder @AllArgsConstructor @NoArgsConstructor public class User { private Integer age; private String name; private Long id; }</p> <pre><code> 字段顺序随便放,最后再执行一下:
User(age=2, name=3, id=1)
User(age=3, name=hhhh, id=2)

Original: https://www.cnblogs.com/eaglelihh/p/15459073.html
Author: eaglelihh
Title: mybatis竟然报”Invalid value for getInt()”

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/587207/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 虚拟机 centos web nodejs服务 外网映射

    虚拟机 centos web nodejs服务 外网映射 起因 为了不买云服务器也是拼了 安装虚拟机 VMware-Workstation-Lite-15.5.1-15018445…

    Java 2023年5月30日
    0106
  • eShopOnContainers 是一个基于微服务的.NET Core示例框架

    找到一个好的示例框架很难,但不是不可能。大多数是小型Todo风格的应用程序,通常基于SimpleCRUD。值得庆幸的是,Microsoft已经为eShopOnContainers创…

    Java 2023年6月7日
    081
  • 50道Redis高频面试题(1-12)

    一、Redis到底是单线程还是多线程 Redis 6.0版本之前的单线程指的是其网络I/O和键值对读写是由一个线程完成。也就是只有网络请求模块和数据操作模块是单线程的,而其他的持久…

    Java 2023年6月9日
    074
  • 基于Socket实现多人聊天室

    1 package com.example.demo.socket; 2 3 import org.springframework.util.ObjectUtils; 4 5 im…

    Java 2023年6月6日
    096
  • LinkedList源码刨析

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月6日
    080
  • 「日志」Navicat统计的行数竟然和表实际行数不一致

    背景 近期为了保障线上数据库的稳定性,我决定针对一些大表的历史数据有计划地进行备份迁移,但是呢,发现一个奇特的现象,Navicat统计行数和表自身count统计数竟然不一致!?0….

    Java 2023年6月13日
    076
  • 内存

    内存分析 Java虚拟机的内存大分为三个区域:栈,堆和方法区,其实细分是只有两个,因为方法区也是在堆里的。 栈(stack): 每个方法被调用都会创建一个栈帧,用以存储局部变量、操…

    Java 2023年6月5日
    091
  • 【转】【WPF】WPF强制刷新界面

    Winform 里有 Application.DoEvents();可刷新! WPF 里没这个,尽管可用委托实现多线程,但是刷新还是不行! 后来找到了 类似App.DoEvents…

    Java 2023年5月29日
    070
  • springmvc框架快速入门

    (1)创建一个maven得web工程 (2)引入springmvc的依赖 1 2 3 org.springframework 4 spring-webmvc 5 5.3.4 6 7…

    Java 2023年6月5日
    087
  • 解决SpringBoot jar包中的文件读取问题

    前言 SpringBoot微服务已成为业界主流,从开发到部署都非常省时省力,但是最近小明开发时遇到一个问题:在代码中读取资源文件(比如word文档、导出模版等),本地开发时可以正常…

    Java 2023年6月14日
    081
  • 再也不担心构建问题了

    希望这篇文章可以理清这个工具,了解其使用。 前言 说真的,autotools工具让我很头疼,各种类似的工具 autolocal , automake 以及生产各种相似的文件 Mak…

    Java 2023年5月30日
    067
  • MQ的消息丢失/重复/积压的问题解决

    在我们实际的开发过程中,我们肯定会用到MQ中间件,常见的MQ中间件有kafka,RabbitMQ,RocketMQ。在使用的过程中,我们必须要考虑这样一个问题,在使用MQ的时候,我…

    Java 2023年6月7日
    079
  • fastposter v2.8.3 发布 电商海报生成器

    fastposter v2.8.3 发布 电商海报生成器 🔥🔥🔥 fastposter海报生成器,电商海报编辑器,电商海报设计器,fast快速生成海报 海报制作 海报开发。贰维🐴海…

    Java 2023年6月5日
    076
  • 1、数组

    <span class=”pun”>&#x6570;&#x7EC4;&#x662F;&#x4E00;&#x79CD;&#…

    Java 2023年6月6日
    079
  • Virtualbox中不能为虚拟机打开一个新任务的原因及解决方法

    我最开始的时候还以为是因为我的虚拟机路径是中文导致的,后来才发现原因: 4.3.12 之后的版本增加了安全检查机制(以前会被病毒利用),如果有程序将DLL注入Vbox的进程就会报错…

    Java 2023年5月30日
    0112
  • idea自定义类注释

    演示用的idea 版本为2020.1 步骤一: 选择File —-Settings 步骤二: 选择 Live Templates—-选择加号—选择 Temp…

    Java 2023年6月13日
    088
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球