ibatis2.3.4.726问题二

假设:

public class Account {

private Integer id;
private String firstName;
private String lastName;
private String emailAddress;
//新增一个Object类型的组合对象
private Object primaryKey;
//....
}

maping配置:

<select id="selectAccount" parameterClass="Account" resultMap="AccountResult">
select
ACC_ID ,
ACC_FIRST_NAME ,
ACC_LAST_NAME ,
ACC_EMAIL
from ACCOUNT
<dynamic prepend="where">
<isEqual property="primaryKey.id" prepend="and" compareValue="1">
ACC_ID = 2
</isEqual>
</dynamic>
</select>

程序中代码:

Account a = new Account();
Account a2 = new Account();
a2.setId(new Integer(1));
a.setPrimaryKey(a2);

List list = (List) sqlMapper.queryForList("selectAccount", a);

很不幸,会报告Object类中没有id属性。why?
这个问题原因,是因为ibatis在判断属性值的时候,不是运行时候动态从设置的对象中获取,而是直接从缓存中获取确切的配置类信息:
com.ibatis.common.beans.ComplexBeanProbe中的代码:

public Class getPropertyTypeForGetter(Object object, String name) {
Class type = object.getClass();

if (object instanceof Class) {
type = getClassPropertyTypeForGetter((Class) object, name);
} else if (object instanceof Map) {
Map map = (Map) object;
Object value = map.get(name);
if (value == null) {
type = Object.class;
} else {
type = value.getClass();
}
} else {
if (name.indexOf('.') > -1) {
StringTokenizer parser = new StringTokenizer(name, ".");
while (parser.hasMoreTokens()) {
name = parser.nextToken();
//看看这里的type你会全明白了
type = ClassInfo.getInstance(type).getGetterType(name);
}
} else {
type = ClassInfo.getInstance(type).getGetterType(name);
}
}

return type;
}

com.ibatis.common.beans.ClassInfo中getGetterType方法

public Class getGetterType(String propertyName) {
Class clazz = (Class) getTypes.get(propertyName);
if (clazz == null) {
throw new ProbeException("There is no READABLE property named '" + propertyName + "' in class '" + className + "'");
}
return clazz;
}


解决方法是使用反射获取真实的对象信息:

public Class getPropertyTypeForSetter(Object object, String name) {
Class type = object.getClass();

if (object instanceof Class) {
type = getClassPropertyTypeForSetter((Class) object, name);
} else if (object instanceof Map) {
Map map = (Map) object;
Object value = map.get(name);
if (value == null) {
type = Object.class;
} else {
type = value.getClass();
}
} else {
if (name.indexOf('.') > -1) {
//用以下代码替代了上面StringTokenizer部分,其它地方同理。
//虽然反射效率较低,但此次使用反射可以让程序有更大的灵活性
String[] names = name.split("\\.");
for (int i = 0; i < names.length; ++i) {
try {
Method method = ClassInfo.getInstance(type).getGetter(names[i]);
object = method.invoke(object, new Object[]{});
if (object != null) {
type = object.getClass();
} else {
type = null;
break;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} else {
type = ClassInfo.getInstance(type).getSetterType(name);
}
}

return type;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值