一次泛型引起的意外:java.math.BigDecimal cannot be cast to java.lang.Integer

本文详细解析了一个关于MyBatis在处理泛型时出现的类型转换异常问题,包括错误日志分析、代码审查及解决方案。通过调整XML配置文件中的类型映射,成功将返回值类型从BigDecimal更改为Integer。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

咱们按照发现问题、分析问题、解决问题的思路看一下这个问题吧。


首先看看这个云里雾里的错误日志:

Caused by: java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Integer

然后根据错误日志里提示的行数找到出问题的代码行,这个方法很简单,是由Mybatis根据主键查询并返回Java对象。


检查一下Mybatis的配置:

<?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.test.TestDao" >
  <resultMap id="BaseResultMap" type="com.test.Test" >
    <id column="ID" property="id" /> 

注意数据库字段ID和id的对应关系没有配置类型,这里Mybatis会自动返回一个java.math.BigDecimal对象。


再看看com.test.Test这个类的ID是不是BigDecimal类型的吧

public class Test extends SuperTest<Integer> implements Serializable {
    此类里没有id的定义,是在父类里定义的
}

接着看父类:

public abstract class SuperTest<ID> {
	
	private ID id;

	public ID getId() {
		return this.id;
	}

	public void setId(ID id) {
		this.id = id;
	}
        省略其他代码...
}


这里为何子类明明设定了泛型是Integer,但是最后却成了BigDecimal了呢?
原因是这样子的:
首先我们要知道在编译后会将泛型转换为Object对象的,这是为了向JDK1.5之前的版本兼容。
但是会在Test类中增加一些父类的桥方法,类就成这样了:

public class Test extends SuperTest<Integer> implements Serializable {
        public Integer getId() {
		return (Integer)this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}
}



父类编译后成了这样子:

public abstract class SuperTest<ID> {
	private Object id;

	public Object getId() {
		return this.id;
	}

	public void setId(Object id) {
		this.id = id;
	}
        省略其他代码...
}

当Mybatis获取的对象返回的id是BigDecimal时,就通过Test来设置,但是没有找到setId(  BigDecimal id)的定义,于是就找到其父类setId( Object id),于是返回的对象就变成了:


Test(){
        id:类型是BigDecimal,而不是Integer
}

这个问题如何解决呢?
很简单,限制Mybatis返回的id是Integer就可以了,看下面的代码:

<?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.test.TestDao" >
  <resultMap id="BaseResultMap" type="com.test.Test" >
    <id column="ID" property="id" javaType="int" jdbcType="INTEGER"/> 

问题迎刃而解。
这个问题是因为泛型的类型擦除有关,在有泛型的地方,一定要对此加以注意。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值