mybatis执行长难sql语句-通过反射替换mybatis绑定的sql语句

终于接触一点mybatis高阶一点的用法了 真实知识是个浩瀚无垠的海洋啊

正文

今天遇到的业务场景是这样的。两个数据库,主库和从库,希望通过springboot项目把主库中的表结构同步到从库中。也就是在从库中建表,但表结构不确定。因此不能使用统一的sql语句,需要根据不同表拼接sql。

  • 所以主要学习了一下mybatis的进阶知识;
  • 看过技术文献后我的解决办法主要是通过反射把要执行的sql语句替换成自己已经拼接好的。

我主要看的文档是这个 <mybatis技术文档链接>
以及通过idea看一点源码;
重新把自己的感悟写一下

mybatis

数据库接口层

这个是和数据库打交道,直接对数据库增删改查。主要涉及到的执行类为SqlSession
SqlSessionFactory—>SqlSession
SqlSession 可以直接执行相应的statement,也可以通过Mapper接口执行;

sql绑定与结果解析

主要涉及到了

  • BoundSql绑定具体sql语句;
  • SqlSource 构建BoundSql对象;
  • MappedStatement 每个注解或者xml中的sql函数对应一个MappedStatement
  • Configuration mybatis外部配置类
  • ResultMap 具体查询结果与java中类的转换

所以,看到这些后我主要想到:把BoundSql中的sql语句绑定成我自己的就好了。

框架支撑
  • 注解配置sql语句
  • xml配置sql语句

我的动态sql语句生成类:

public List<String> createTableSql(DbTableInfo dbTableInfo) {
		List<String> sqls = Collections.emptyList();
		
		if (dbTableInfo != null && dbTableInfo.getTableStructure() != null
				&& !dbTableInfo.getTableStructure().isEmpty()) {
			sqls = dbTableInfo.getTableStructure().entrySet().stream().map(e -> {
				StringBuilder sb = new StringBuilder();
				sb.append("CREATE TABLE `" + e.getKey() + "` (");
				List<RowInfo> rows = e.getValue();
				for (RowInfo row : rows) {
					sb.append("`" + row.getFieldName() + "` ");
					sb.append(row.getFieldType() + " COMMENT '" + row.getFieldComment() + "',");
				}
				String tempSql = sb.toString();
				String sql = tempSql.substring(0, tempSql.length() - 1) + ");";
				return sql;
			}).collect(Collectors.toList());
		}
		return sqls;
	}

通过反射获得具体feild,并将对象的feild重新设置:

private void dynamicReplaceSqlStatementIfNecessary(String sql, String sqlStatementId) {
		if (StringUtils.hasText(sql)) {
			Configuration configuration = sqlSessionFactory.getConfiguration();
			MappedStatement mappedStatement = configuration.getMappedStatement(sqlStatementId);
			SqlSource sqlSource = mappedStatement.getSqlSource();
			if (sqlSource instanceof StaticSqlSource && sqlSource.getBoundSql(null).getSql().equalsIgnoreCase(sql)) {
				return;
			}
			try {
				Field sqlSourceField = mappedStatement.getClass().getDeclaredField("sqlSource");//反射
				sqlSourceField.setAccessible(true);
				sqlSourceField.set(mappedStatement, new StaticSqlSource(mappedStatement.getConfiguration(), sql));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

还是要多看源码,多看大神总结的文章啊。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值