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() - 'wo'
场景
还原一下当时的情况:
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));
}
}
}
数据库如下:

上面是一个很简单的例子,就是根据id选出用户的信息,运行结果如下:
User(id=1, age=2, name=3)
没有任何问题,但是我再往数据库里插入一条数据,如下:

在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() - 'lh'
……
可以看出第一条查询没有问题,第二条查询就报错了
初探
其实我的直觉告诉我,是不是因为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=lh, 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=lh)
再探
其实到上一步,问题已经解决了,可以继续干活了,但是搞不懂为什么,心里总觉得不踏实。
找bug从debug开始,从下面的入口开始:

追踪到如下:


可以看出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了,如下:
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer age;
private String name;
private Long id;
}
字段顺序随便放,最后再执行一下:
User(age=2, name=3, id=1)
User(age=3, name=lh, id=2)
mybatis竟然报"Invalid value for getInt()"的更多相关文章
- 【mybatis】mybatis访问报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 或者 feign被调用方使用的mybatis总报空指针异常java.lang.NullPointerException,而变量都没有问题的情况
mybatis访问报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 需要检查的步骤: ...
- mybatis 报Invalid bound statement(not found) 和 Property 'mapperLocations' was not specified or not matching resources found
排除问题的步骤: 1.首先检查mapper文件和mapper接口的文件名是否相等. 2.pom.xml是否把xml排除了,这样写就会src/main/java下所有的Mybatis的xml文件都删除, ...
- JavaWeb报错:java.sql.SQLException: Invalid value for getInt()
1.错误描述:在对数据库进行操作时,控制台报错:java.sql.SQLException: Invalid value for getInt() :2.错误原因:数据库中表的字段的类型与实体类中属性 ...
- Error getting nested result map values for 'company'. Cause: java.sql.SQLException: Invalid value for getInt() - 'NFHK188'
我今天遇到一个我不解的问题,是mybatis多对一关系查询出问题了,但是我自己还是解决了,在网上也查过那个错误,可是找不到我想要的.不知道你们遇到过没有,我接下来分享给大家.希望我这个第一篇博客能帮助 ...
- Android Studio Linking an external C++ project 时候 报Invalid file name. Expected: CMakeLists.txt
Android Studio 右键Linking an external C++ project 时候 报Invalid file name. Expected: CMakeLists.txt错误 查 ...
- CCLuaObjcBridge调Objective-C方法传索引数组报invalid key to 'next'错调试
CCLuaObjcBridge是cocos2d-x系列引擎与Objective-C进行交互的"桥梁",老廖的quick-cocos2d-x在其framework进行了简单了封装,封 ...
- spring 整合Mybatis 《报错集合,总结更新》
错误:java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldExcepti ...
- virtual box未卸载报"Invalid Drive:F:\"的解决方案
=============================================== 20170417_第一次修改 ccb_warlock === ...
- java.sql.SQLException:Invalid value for getInt()-'zhangsan'
1.错误描述 java.sql.SQLException:Invalid value for getInt()-'zhangsan' 2.错误原因 在遍历打印查询结果时,rs.getInt(3),而在 ...
随机推荐
- CodeForce-811C Vladik and Memorable Trip(动态规划)
Vladik and Memorable Trip CodeForces - 811C 有一个长度为 n 的数列,其中第 i 项为 ai. 现在需要你从这个数列中选出一些互不相交的区间,并且保证整个数 ...
- Python+Selenium:初步使用Chrome谷歌浏览器
·············环境结合··············· 我的环境:window10 64位 Python 3.7 32-bit selenium 3.141.0 Goo ...
- CDI Features inJavaEE 的上下文和依赖注入
基本的CDI的功能: 类型安全:CDI使用Java类型来解析注入,而不是通过(字符串)名称注入对象.当类型不足时, 可以使用限定符 注释.这允许编译器轻松检测错误,并提供简单的重构. POJO:几乎每 ...
- Mixed Content: The page at 'xxx' was loaded over HTTPS, but requested an insecure resource 'xxx'.
HTTPS页面里动态的引入HTTP资源,比如引入一个js文件,会被直接block掉的.在HTTPS页面里通过AJAX的方式请求HTTP资源,也会被直接block掉的. Mixed Content: T ...
- 开源ASR服务器vosk
概述 近几年由于AI的迅速发展,语音相关的自然语言处理NLP项目也变多了,新的技术也越来越成熟,其中TTS(语音生成)和ASR(语音识别)是NLP中非常重要的环节. 今天我们介绍一个开源的ASR项目v ...
- layui 各项配置
第一.如何全部选中table中每一条记录 1.首先给table的父类设置一个唯一id *这种方式不推荐,效果比较差,推荐第2种方式 再搜索 alias-table div.layui-table-fi ...
- shell加密为二进制可执行文件
1.下载shc工具 http://www.datsi.fi.upm.es/~frosal/sources/shc-3.8.9.tgz或者到http://www.datsi.fi.upm.es/~fro ...
- Windows环境下搭建Hadoop(2.6.0)+Hive(2.2.0)环境并连接Kettle(6.0)
前提:配置JDK1.8环境,并配置相应的环境变量,JAVA_HOME 一.Hadoop的安装 1.1 下载Hadoop (2.6.0) http://hadoop.apache.org/release ...
- iOS Swift逻辑运算符
运算符 运算符分类 从操作数角度看:运算符包括一元.二元.三元.这里的一二三指操作数的数量,操作数指的是被操作的数值. 从运算符位置看:运算符分为前缀.中缀.后缀.例如:!b, b + c, c! 赋 ...
- 第21篇-加载与存储指令之iload、_fast_iload等(3)
iload会将int类型的本地变量推送至栈顶.模板定义如下: def(Bytecodes::_iload , ubcp|____|clvm|____, vtos, itos, iload , _ ); ...