咱们按照发现问题、分析问题、解决问题的思路看一下这个问题吧。
然后根据错误日志里提示的行数找到出问题的代码行,这个方法很简单,是由Mybatis根据主键查询并返回Java对象。
注意数据库字段ID和id的对应关系没有配置类型,这里Mybatis会自动返回一个java.math.BigDecimal对象。
这里为何子类明明设定了泛型是Integer,但是最后却成了BigDecimal了呢?
原因是这样子的:
首先我们要知道在编译后会将泛型转换为Object对象的,这是为了向JDK1.5之前的版本兼容。
但是会在Test类中增加一些父类的桥方法,类就成这样了:
首先看看这个云里雾里的错误日志:
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"/>
问题迎刃而解。
这个问题是因为泛型的类型擦除有关,在有泛型的地方,一定要对此加以注意。