问题描述
连ORALCE数据库,想搞一个BaseService通用查询,然后发现被查的表中都有一个VersionID字段,需求是只需要取最大VersionID的记录即可。这个字段 是一个BigDecimal的,那就想着通过反射反回这个字段值,然后再拼查询条件…
报错的代码如下:
public int maxVersion(BaseMapper<T> mapper) throws Exception {
QueryWrapper wrapper = new QueryWrapper();
wrapper.select("VERSIONID").eq("rownum", 1);
wrapper.orderByDesc("VERSIONID");
T t = (T) mapper.selectOne(((QueryWrapper) wrapper));
Object value = null;
if (null != t) {
Field fields[] = t.getClass().getDeclaredFields();
for (Field field : fields) {
String name = field.getName().toUpperCase();
String type = field.getAnnotatedType().getType().getTypeName();
if ("VERSIONID".equals(name)) {
field.setAccessible(true);
if ("java.math.BigDecimal".equals(type)) {
BigDecimal bigDecimalVar = new BigDecimal(field.get(name).toString());
System.out.println(bigDecimalVar);
}
}
}
报错如下所示:
java.lang.IllegalArgumentException: Attempt to get java.math.BigDecimal field "xxx.versionid" with illegal data type conversion to long
解决问题
试了好多咱转型方案,并跟踪源码,其判断逻辑是在调用field.get(name)时,选择UnsafeObjectFieldAccessorImpl类解析,然后在ensureObj(varl)方法中判断类型是否一臻时报的错,
protected void ensureObj(Object var1) {
if (!this.field.getDeclaringClass().isAssignableFrom(var1.getClass())) {
this.throwSetIllegalArgumentException(var1);
}
}
想放弃了,后来想着把这个对象转成map看看能否成功,结果这个问题解决了,终于可以取到值了,反射也省了。上述报错的方法改为:
public int maxVersion(BaseMapper<T> mapper) throws Exception {
QueryWrapper wrapper = new QueryWrapper();
wrapper.select("VERSIONID").eq("rownum", 1);
wrapper.orderByDesc("VERSIONID");
T t = (T) mapper.selectOne(((QueryWrapper) wrapper));
int maxVersion = 0;
if (null != t) {
BeanMap beanMap = BeanMap.create(t);
for (Object key : beanMap.keySet()) {
if ("VERSIONID".equals(key.toString().toUpperCase())) {
System.out.println(beanMap.get(key));
maxVersion = Integer.parseInt(beanMap.get(key).toString());
}
}
}
return maxVersion;
}