会不会有这种需求,我的sql不是写在代码、xml里面,而是从数据库里面加载出来的。还可以修改sql。
直接执行sql,又想要mybatis的标签表达式<where><if><foreach> 分页。切换数据源就能完成不同数据库之间的特性。
之前写了一篇扩展mybaits批量修改的文章,今天同样的代码参考也是tk.mybatis。
先上代码
代码不多,基本上就是一步一步的往下走
1.创建sql解析对象 SqlSource 2.创建mybaits的映射对象 MappedStatement 3.方法入参 ParameterMap 4.方法出参 ResultMap 5.添加到config configuration.addMappedStatement(test001.build());
package com.convertlab.rili.bi;
import com.alibaba.fastjson.JSON;
import com.convertlab.rili.bi.user.bean.po.User;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/**
* @author lanyanhua
* @date 2022/4/12 10:51 上午
* @description
*/
@ActiveProfiles("dev")
@SpringBootTest
public class MybatisTest {
@Autowired
private SqlSessionFactory sqlSessionFactory;
@Test
public void test() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Object> executeSql = sqlSession.selectList("com.convertlab.rili.bi.business.mapper.AuditLogMapper.selectById", 1);
System.out.println(executeSql.size());
}
@Test
public void configuration() {
MappedStatement test = null;
Configuration configuration = sqlSessionFactory.getConfiguration();
for (Object object : new ArrayList<Object>(configuration.getMappedStatements())) {
if (object instanceof MappedStatement) {
MappedStatement ms = (MappedStatement) object;
if (ms.getId().equals("com.convertlab.rili.bi.business.mapper.AuditLogMapper.selectById")) {
test = ms;
}
}
}
String sql = "select * from TB_USER where id = #{id} <if test=\"id1 != null\">or id = #{id1} </if>";
//xml解析驱动
final XMLLanguageDriver languageDriver = new XMLLanguageDriver();
SqlSource sqlSource = languageDriver.createSqlSource(configuration,
"<script>\n\t" + sql + "</script>", null);
//id sql
MappedStatement.Builder test001 = new MappedStatement.Builder(configuration, "com.convertlab.rili.bi.test001", sqlSource, SqlCommandType.SELECT);
// MetaObject msObject = forObject(test001);
// msObject.setValue("resultSetType", test.getResultSetType());
//返回参数类型
ResultMap.Builder builder = new ResultMap.Builder(configuration, "test001.resultMap", User.class, new ArrayList<>());
test001.resultMaps(Collections.singletonList(builder.build()));
//入参
ParameterMap.Builder builder1 = new ParameterMap.Builder(configuration, "test001.param", HashMap.class, new ArrayList<>());
test001.parameterMap(builder1.build());
configuration.addMappedStatement(test001.build());
System.out.println();
SqlSession sqlSession = sqlSessionFactory.openSession();
//测试
HashMap<String, Object> param = new HashMap<>();
param.put("id", 1);
param.put("id1", 2);
// param.put("id1",2);
List<Object> executeSql = sqlSession.selectList("com.convertlab.rili.bi.test001", param);
System.out.println(JSON.toJSONString(executeSql));
executeSql = sqlSession.selectList("com.convertlab.rili.bi.business.mapper.AuditLogMapper.selectById", param);
System.out.println(JSON.toJSONString(executeSql));
sqlSession.close();
}
}
这个代码网上没有找到相关资料(关键字实在没憋出个好屁)参考的tk.mybatis里面是写的替换更新掉已用的sql
//需要写修改替换当前sql的可以参考一下 tk.mybatis的这段源代码
//tk.mybatis.mapper.mapperhelper.MapperTemplate.setSqlSource()
/**
* 重新设置SqlSource
*
* @param ms
* @param sqlSource
*/
protected void setSqlSource(MappedStatement ms, SqlSource sqlSource) {
MetaObject msObject = MetaObjectUtil.forObject(ms);
msObject.setValue("sqlSource", sqlSource);
}
几个需要注意的点:
你要是执行代码、xml里面的sql,控制台打印出来了sql,而这里添加的却没有打印,代码是没有问题的,而是ID的问题。
在MappedStatement类中有这么一个字段。可以看到logger的那一 串地址Logger[com.convertlab.rili.bi.business.mapper.AuditLogMapper.selectById]
有想到什么吗,就是配置文件里面日志的级别配置这里。所以想要打印日志MappedStatement的ID就不要乱写