上一篇介绍了Mybatis如何获取查询接口的有序参数列表,这一篇会结合上一篇的内容解决实际问题,最近遇到了查询报表并将查询内容导出Excel文件的实际场景,需要获取到查询的完整SQL再通过导出工具导出Excel。
主要代码如下
//methodPath为执行方法的全限定名
//map为methodPath的参数列表,在查询接口多参数和单个参数的情况下会有一点差别
public String InSql(String methodPath, Map<String, Object> map) {
BoundSql boundSql = sqlSessionFactory.getConfiguration().getMappedStatement(methodPath).getBoundSql(map);
String sql = boundSql.getSql();
//根据SQL获取参数列表
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
//定义集合存储映射参数
List<Object> paramList = new ArrayList<>();
//foreach标签标记 只进入if判断一次即把对应参数全部存入Set
//由于foreach标签生成的元素的以"__frch_"开头的格式
Set<String> flagSet = new HashSet<>();
for (ParameterMapping pm : parameterMappings) {
//判断是否为输入参数
if (pm.getMode() != ParameterMode.OUT) {
//获取Dao接口参数名
String paramName = pm.getProperty();
if (paramName.contains("__frch_")) {
int firstIndex = paramName.lastIndexOf("_", paramName.lastIndexOf("_") - 1);
int lastIndex = paramName.lastIndexOf("_");
//获取参数名称,这里获取到的参数名为XML文件中foreach标签中的item元素的值,这个值需要与第二层参数列表map设置的key保持一致才能获取到value。
paramName = paramName.substring(firstIndex + 1, lastIndex);
if (!flagSet.contains(paramName)) {
Map param = (Map) map.get("param");
String paramValues = (String) param.get(paramName);
String[] strings = paramValues.split(",");
for (String value : strings) {
paramList.add(value);
}
flagSet.add(paramName);
}
} else if (paramName.contains("param.")) {
paramName = paramName.replace("param.", "");
Map param = (Map) map.get("param");
Object paramValue = param.get(paramName);
paramList.add(paramValue);
} else {
Object o = map.get(paramName);
paramList.add(o);
}
}
}
while (sql.indexOf("?") != -1 && paramList != null && paramList.size() > 0 && paramList.get(0) != null) {
Object paramValue = paramList.get(0);
if (paramValue != null) {
String value = "\'" + paramValue.toString() + "\'";
/*if (paramValue instanceof String){
value = "\'"+paramValue.toString()+"\'";
}else if(paramValue instanceof Date || paramValue instanceof Timestamp){
value = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", (Date) paramValue);
value = "str_to_date('" + value + "','%Y-%m-%d %T')";
}*/
sql = sql.replaceFirst("\\?", value);
paramList.remove(0);
}
}
return sql;
}
多个参数封装
//查询接口
List<Map<String,Object>> getCarBackupData(@Param("currentUserId") int currentUserId, @Param("param") YsSearchCarParam param);
假设需要获取上面多参数接口的完整SQL,封装map参数:
Map<String,Object> param = new hashmap();
//在查询接口获取到currentUserId的值
param.put("currentUserId",param.getCurrentUserId);
//封装第二个map,key为XML文件中判断条件的字符串,value为判断条件的值
Map<String,Obejct> map = new hashMap();
map.put("yy1","yy1");
//在XML文件解析时,xx2被foreach标签解析
//生成类似于__frch_xx0:xx1,__frch_xx1:xx2,__frch__xx2:xx3的三个额外参数
map.put("xx2","xx1,xx2,xx3");
//再由最外层的map将第二参数的值封装起来,这里的键是@param设置的值
param.put("param",map);
单个参数封装
//查询接口
List<YsPeopleResult> selectPeopleLibResultList(YsSearchPeopleParam param);
//直接将SQL中需要的过滤参数放入map即可,map的键为XML文件中对应判断条件字符串
Map<String, Object> map = new HashMap<>();
map.put("searchNum", pici);
如果有bug或问题,欢迎各位在评论区交流。