mybatis解析sql xml脚本记录

时光总嘲笑我的痴心妄想 提交于 2020-03-02 07:46:07

需要给activiti的query接口新增查询条件,但是activiti内部具体基本都是基于实现类,无法扩展。只好使用nativequery接口写sql。然后就想到直接copy复用activiti内部的sql语句。

include标签只能自己用方法字符串去拼接,动态逻辑标签还是可以用mybatis内部实现去解析。另外查询类get的时候会调用到activiti的查询操作,所以在外层还需要加上activiti的壳(使用命令模式,中间加入拦截链,执行操作必须经过拦截链如:日志,事务,上下文,缓存批处理): procEngineCfg.getCommandExecutor().execute(command)

主要的代码整理出来当作备忘:

String XML_PREFIX="<mapper namespace=\"\"><select id=\"temp\">";
String XML_SUFFIX="</select></mapper>";

//获得mybatis的Configuration
Configuration myCfg=procEngineCfg.getMybatisConfiguraton();
//继承HashMap,把xxx:activiti的查询类实例用BeanWrapper包装
ContextMap param=new ContextMap(xxx);
//另外查询条件
param.put("yyy","zzz"); 

//获得sql脚本
String sqlScript=getSelectTaskByQueryCriteria();

//加载sql的xml,解析${},生成XNode(一个Dom API中的Node接口的扩展类)
XPathParser parser=new XPathParser(new ByteArrayInputStream((XML_PREFIX+sqlScript+XML_SUFFIX).getBytes()), false);
XNode xnode=parser.evalNode("/mapper/select");

//从XNode解析xml中的每个标签(如trim,if标签),把XNode转成sqlNode,生成SqlSource
XMLScriptBuilder builder = new XMLScriptBuilder(myCfg, xnode, Map.class);
SqlSource taskByQueryCriteriaSS=builder.parseScriptNode();

//sqlSource里的sqlNode解析逻辑标签后生成BoundSql 带#{}的sql 和 参数
//BoundSql封装mybatis最终产生sql的类,包括sql语句,参数,参数源数据等参数
BoundSql boundSql=taskByQueryCriteriaSS.getBoundSql(param);

//获取参数值
Map<String,Object> params=new LinkedHashMap<String, Object>();
Object parameterObject=boundSql.getParameterObject(); 
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();

if (parameterMappings == null)
	return params;

//循环设参数
for (int i = 0; i < parameterMappings.size(); i++) 
{
	ParameterMapping parameterMapping = parameterMappings.get(i);
    if (parameterMapping.getMode() == ParameterMode.OUT)
    	continue;

    //如果不是OUT,才设进去
    Object value;
    String propertyName = parameterMapping.getProperty();
    if (boundSql.hasAdditionalParameter(propertyName)) //若有额外的参数, 设为额外的参数 issue #448 ask first for additional params
        value = boundSql.getAdditionalParameter(propertyName);
    else if (parameterObject == null) //若参数为null,直接设null
        value = null;
    else if (myCfg.getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass())) //若参数有相应的TypeHandler,直接设object
        value = parameterObject;
    else 
    {
        //除此以外,MetaObject.getValue反射取得值设进去
        MetaObject metaObject = myCfg.newMetaObject(parameterObject);
        value = metaObject.getValue(propertyName);
    }
    params.put(String.valueOf(i), value);
}

class ContextMap extends HashMap<String, Object> 
{
	private static final long serialVersionUID = 1L;

    private BeanWrapper beanWrapper;
    public ContextMap(Object obj) {
    	beanWrapper= PropertyAccessorFactory.forBeanPropertyAccess(obj);
    }

    @Override
    public Object get(Object key) 
    {
    	String strKey = (String) key;
    	if (super.containsKey(strKey)) 
    		return super.get(strKey);

    	if (beanWrapper != null)
    		return beanWrapper.getPropertyValue(strKey);

    	return null;
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!