mybatis里的REGEXP

clipboard.png
红框部分(,sum(if(Item_169 REGEXP '^[0-9]{1,12}(.[0-9]{1,5})?$',Item_169,0)))后台传入mybatis配置文件(配置文件用${}接收),整个sql复制到mysql数据库正常运行;这个问题怎么解决

阅读 11.1k
3 个回答

问题:不是正则表达式的问题,而是Mybatis类型转化的问题

解决方案:为sum的结果添加一个别名data

sum(if(item REGEXP '^[0-9]{1,12}(.[0-9]{1,5})?$',item,0)) as data 

问题原因

TZ的mapper文件可简化为如下文件

<select id="select" resultType="java.util.Map">
    SELECT sum(if(item REGEXP '^[0-9]{1,12}(.[0-9]{1,5})?$',item,0)) FROM user
</select>

问题在于Mybatis对结果的属性设置,由于返回结果的类型为java.util.Map,调用函数DefaultResultSetHandler.createAutomaticMappings(**),

首先获取参数类型:

  final Class<?> propertyType = metaObject.getSetterType(property);

接着我们会看到PropertyTokenizer(属性标记器),主要用来处理反射类的属性名,

传入:User[1].age 
name=User 
children=age 
index=1

问题就出在这个地方。

public class PropertyTokenizer{
    private String name;
    private String index;
    private String indexedName;
    private String children;

    public PropertyTokenizer(String propertyName) {
        // 对参数进行第一次处理,通过“.”分隔符将propertyName分作两部分
        int delimiter = propertyName.indexOf(".");
        if (delimiter > -1) {
            name = propertyName.substring(0, delimiter);
            children = propertyName.substring(delimiter + 1);
        } else {
            name = propertyName;
            children = null;
        }
        indexedName = name;
        // 对name进行二次处理,去除“[...]”,并将方括号内的内容赋给index属性,如果name属性中包含“[]”的话
        delimiter = propertyName.indexOf("[");
        if (delimiter > -1) {
            // 先取index内容再截取name更为方便些,要不然还需要一个临时变量,需要三步才能实现
            // 这里包含了一个前提:传入的参数如果有有[,则必然存在],并且是属性的最后一个字符
            index = name.substring(delimiter + 1, name.length() - 1);
            name = name.substring(0, delimiter);
        }
    }
 }

这里propertyName 是 sum(if(item REGEXP '^[0-9]{1,12}(.[0-9]{1,5})?$',item,0)),得到的PropertyTokenizer对象内容如下:

 prop = {PropertyTokenizer@4448} 
 name = "sum(if(item REGEXP '^"
 indexedName = "sum(if(item REGEXP '^[0-9]{1,12}("
 index = "0-9]{1,12}"
 children = "[0-9]{1,5})?$',item,0))"

接着根据prop.getIndex()判断结果是一个集合对象,实际上结果就是一个Double对象,抛出一个类型错误。
所以建议不使用java.lang.Map类型作为结果,一般自定义对象或者建立resultMap类型。

<![CDATA[表达式内容]]>
试试

你问过我这个问题。。

MyBatis的错误不在查询过程,而在于对ResultSet处理时,你这列名字有问题导致的。

所以很简单,你起个别名就解决了!已经测试过了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题