Mybatis报错: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character

本文详细解析了在使用MyBatis进行数据库插入操作时遇到的错误,具体为参数类型不匹配问题,即字符串无法转换为字符类型,通过调整参数类型及JDBC配置成功解决了该问题。

1.问题描述:mybatis中Insert的时候一直报错,在网上找了很久的答案没找到,结果自己debug知道在那一块出错了,然后各种调试,结果测通了三天前的问题。

2.直接上问题(idea编译器):

DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 2005167404.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@77846d2c]
DEBUG [main] - ==>  Preparing: INSERT INTO t_user(uname,sex,address,birthday) VALUES(?,?,?,?); 

org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='sex', mode=IN, javaType=char, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #2 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character
### The error may involve user.insertUser-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO t_user(uname,sex,address,birthday) VALUES(?,?,?,?);
### Cause: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='sex', mode=IN, javaType=char, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #2 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character

    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
    at com.tydic.test.UserTest.testinsertUser(UserTest.java:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:305)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:365)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:330)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:78)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:328)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:65)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:292)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:305)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:412)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='sex', mode=IN, javaType=char, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #2 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character
    at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:89)
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:93)
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:64)
    at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:86)
    at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
    at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
    at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
    ... 27 more
Caused by: org.apache.ibatis.type.TypeException: Error setting non null for parameter #2 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character
    at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:55)
    at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87)
    ... 34 more
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character
    at org.apache.ibatis.type.CharacterTypeHandler.setNonNullParameter(CharacterTypeHandler.java:26)
    at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:53)
    ... 35 more

3.原来的代码如图标记:

4.解决的方法(idea编译器自动添加的参数的前缀,导致上面的报错):

5.正常运行(结果)完美解决:

Always keep the faith!!!

### SQL 查询中 `ClassCastException` 的原因分析 当遇到错误提示 `java.lang.String cannot be cast to java.lang.Integer` 时,表明应用程序试图将字符串类型的对象强制转换为整数类型。这种异常通常发生在数据处理过程中,特别是在数据库查询结果被映射到 Java 对象时。 #### 数据库字段与实体类属性不匹配 如果数据库中的某个字段存储的是字符串形式的数据(例如 `'1'`, `'abc'`),但在对应的 Java 实体类中定义为 `Integer` 类型,则在执行查询并尝试将该字段赋值给实体类属性时会抛出此异常[^1]。 ```sql -- 假设有一个表 t_user, 其中 age 字段实际存有 '25', 而不是数值 25. SELECT * FROM t_user WHERE id = ? ``` 对于上述情况,在获取记录后将其映射至 User.java 中: ```java public class User { private Integer age; // 应用程序期望这里接收 int 或者 Integer 类型 } ``` 此时就会发生类型转换失败的情况。 ### 解决方案 为了有效解决此类问题,可以采取以下措施之一或者组合使用这些方法来确保正确性和稳定性。 #### 方法一:调整数据库设计 最根本的办法是从源头解决问题——即修改数据库结构使得各列的数据类型与其所代表的意义相吻合。比如把原本保存年龄信息却用了 VARCHAR(255) 这样的字符型改为 TINYINT/SMALLINT/MEDIUMINT/BIGINT 等适合表示数字范围内的合适类型[^2]。 #### 方法二:自定义类型处理器 另一种方式是在应用层面上通过编写自定义的 TypeHandler 来实现更灵活地控制如何解析来自 JDBC 驱动返回的结果集。MyBatis 提供了这样的机制让用户能够指定特定情况下应该如何完成从 ResultSet 到目标 POJO 属性之间的转换逻辑。 ```xml <!-- mybatis-config.xml --> <typeHandlers> <typeHandler handler="com.example.MyCustomTypeHandler"/> </typeHandlers> ``` 以及相应的 Java 文件: ```java package com.example; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class MyCustomTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { try { ps.setInt(i, Integer.parseInt(parameter)); } catch (NumberFormatException e) { throw new RuntimeException("Failed to convert string '" + parameter + "' into integer.", e); } } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return String.valueOf(rs.getInt(columnName)); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return String.valueOf(rs.getInt(columnIndex)); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return String.valueOf(cs.getInt(columnIndex)); } } ``` 这种方法允许开发者针对具体场景定制化处理流程而不必改变底层架构。 #### 方法三:验证输入合法性 无论何时都应该对外部传入参数做必要的校验工作以防止非法值进入系统内部引发不必要的麻烦。可以通过正则表达式或者其他手段确认待操作项确实满足预期格式后再继续后续动作;另外也可以考虑利用框架自带的功能简化这部分开发成本,如 Spring Validation 注解等工具可以帮助快速构建起一套完整的约束体系[^3]。 ### 总结 综上所述,面对 `java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer` 错误,应该先定位其产生的根源在于哪一层级出现了不当的操作行为,再依据实际情况选用合适的策略加以应对。无论是优化数据库模式还是增强业务代码健壮性都是可行的选择方向。
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值