终于接触一点mybatis高阶一点的用法了 真实知识是个浩瀚无垠的海洋啊
正文
今天遇到的业务场景是这样的。两个数据库,主库和从库,希望通过springboot项目把主库中的表结构同步到从库中。也就是在从库中建表,但表结构不确定。因此不能使用统一的sql语句,需要根据不同表拼接sql。
- 所以主要学习了一下mybatis的进阶知识;
- 看过技术文献后我的解决办法主要是通过反射把要执行的sql语句替换成自己已经拼接好的。
我主要看的文档是这个 <mybatis技术文档链接>
以及通过idea看一点源码;
重新把自己的感悟写一下
mybatis
数据库接口层
这个是和数据库打交道,直接对数据库增删改查。主要涉及到的执行类为SqlSession
。
SqlSessionFactory
—>SqlSession
SqlSession
可以直接执行相应的statement,也可以通过Mapper接口执行;
sql绑定与结果解析
主要涉及到了
BoundSql
绑定具体sql语句;SqlSource
构建BoundSql对象;MappedStatement
每个注解或者xml中的sql函数对应一个MappedStatementConfiguration
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();
}
}
}
还是要多看源码,多看大神总结的文章啊。