EOS/iBATIS中根据sql的全名id获取预编译sql

项目场景:

最近需要完成一个需求,根据命名sql的id取到那段执行sql。

以往我们都是前台传递参数和命名SQL的全名路径后,后台逻辑流使用DatabaseExt.queryByNamedSql进行数据查询并导出的。但是我们无法查看DatabaseExt中的queryByNamedSql源码,无法得知如何获取相应的预编译sql。

后续在看了帮助文档后发现EOS7.5中使用的持久层框架是iBATIS,那么我们能否找到iBATIS的API来获取呢?因为这个猜想,接下来我也依照这种思路去查找相应的解决方案(大家也知道iBATIS也是很久很久以前的框架了,而且也不知道EOS使用的是哪个版本,官网的API都已经下架换成MyBatis了,但是架不住公司还在用着普元EOS7.5开发的项目),也终于找到了相应的API,下面展示程序该如何去获取


问题描述:

我们能使用以下代码来获取到对应的预编译sql

package com.mytest;

import java.util.HashMap;
import java.util.Map;

import com.eos.system.annotation.Bizlet;
import com.primeton.das.sql.impl.SqlMapClientManager;
import com.primeton.das.sql.impl.ibatis.sqlmap.client.SqlMapClient;
import com.primeton.das.sql.impl.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
import com.primeton.das.sql.impl.ibatis.sqlmap.engine.mapping.sql.Sql;
import com.primeton.das.sql.impl.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
import com.primeton.das.sql.impl.ibatis.sqlmap.engine.scope.RequestScope;

public class MySqlTest {
	@Bizlet("通过导出系统进行Excel生成")
	public static Map<String,Object> createExcelByExportSystem(Map<String, Object> datas) throws Exception {
		HashMap<String, Object> sqlParam = ((HashMap<String, Object>)datas.get("param"));
		// dataParamKeyValMap为查询数据sql的key-value参数
		HashMap<String, Object> dataParamKeyValMap = new HashMap<String, Object>();
		String exportSql = getSql(datas.get("querySqlUrl").toString(), sqlParam, dataParamKeyValMap);
		System.out.println("获取带?的sql: " + exportSql);
		System.out.println("动态参数Map集合: " + dataParamKeyValMap);
		return null;
	}

	/**
	 * 获取sql的核心方法
	 */
	private static String getSql(String querySqlUrl, HashMap<String, Object> paramMap,
			HashMap<String, Object> paramKeyValMap) {
		// 最主要的代码段: 通过命名sql的ID获取sql语句
		SqlMapClient client = SqlMapClientManager.INSTANCE.getClient();
		MappedStatement mappedStatement = ((ExtendedSqlMapClient) client).getDelegate().getMappedStatement(querySqlUrl);
		Sql sql = mappedStatement.getSql();
		RequestScope requestScope = new RequestScope();
		requestScope.setStatement(mappedStatement);
		// 获取在配置文件中的sql, ##包裹着的变量会返回为?, $$包裹着的会直接替换
		String executeSql = sql.getSql(requestScope, paramMap);
		// sqlParam为动态参数, 数组内的元素值以?的顺序进行返回
		Object[] sqlParam = sql.getParameterMap(requestScope, paramMap).getParameterObjectValues(requestScope, paramMap);

		// 由于我们在namingsqlx配置文件中格式化了sql, 所以这里获取会有多余的字符串, 此处将连续多个空字符串全部替换成单个空格
		executeSql = executeSql.replaceAll("\\s+", " ").trim();
		// 把sql中的双引号替换为单引号, 便于进行序列化
		executeSql = executeSql.replaceAll("\"", "'");

		// 非必要的, 上面实际上已经获取到sql了, 在这里为了能在后续将?参数对应上实参, 我们将参数设置到paramKeyValMap中返回到调用函数
		if (sqlParam != null && sqlParam.length > 0) {
			String param = null;
			// 将?设置为#{param0}, ${param1}等动态参数, 便于转化为mybatis的参数
			for (int i = 0; i < sqlParam.length; i++) {
				param = "#{param" + i + "}";
				// 将param0作为key, sqlParam[i]作为value记录到Map中进行返回
				paramKeyValMap.put("param" + i, sqlParam[i].toString());
				executeSql = executeSql.replaceFirst("[?]", param);
			}
		}
		return executeSql;
	}
}

程序分析:

在上面的程序中,executeSql 就是我们获取到的sql了如果有动态参数的情况,sql中会有 ?作为替换值;
replaceAll是为了替换掉空字符串,如果不替换的话我们在namingsqlx中的制表符,连续的空格都会在executeSql字符串中;
最后的for循环是为了将executeSql中的?替换为#{param0}{param1}这样的值,然后把param0作为paramKeyValMap,param0对应的值作为paramKeyValMap。最后返回的paramKeyValMap值格式为

{
  param0: 实参1,
  param1: 实参2
}

sql的格式为

select field1, field2 from my_table where id=#{param0} and dept=#{param1}

你可能感兴趣的:(普元EOS,普元EOS,java)