解析带有MyBatis语法的SQL字符串,获取最终的可执行SQL

news/2024/10/22 12:26:09/

有一个带有mybatis语法的sql语句,如下:

java">select * from cfg_export_template where id = #{id} <if test='id != null'> AND 1 = 1 </if>

需求是将sql和占位符相关的数据丢给mybatis,获取到最终可执行的SQL。
解决思路:
1、像if、where等动态标签跟#{}这种占位符不一样,动态标签是mybatis是通过xml的结构去解析的,因为我们拿到手的是字符串,如果直接丢给mybats是无法将这些动态标签进行解析的。所以需要构建成xml格式去处理。参考方法getExecutableSql
2、对于#{}这类的占位符在Mybatis预编译语句后会被?所替换,可以使用ParameterHandler去获取到最终的可执行SQL。参考方法replaceParameters

java">public class MyBatisDynamicSqlExecutor {private SqlSessionFactory sqlSessionFactory;public MyBatisDynamicSqlExecutor(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}/*** 执行传递的SQL 预编译后,返回最终可执行的SQL* @param dynamicSql* @param params* @return*/public String getExecutableSql(String dynamicSql, Map<String, Object> params) throws SQLException {//对字符串中的符号转义dynamicSql = StringEscapeUtils.escapeXml10(dynamicSql);params.put("sql", dynamicSql);Configuration configuration = sqlSessionFactory.getConfiguration();String xml = "<select>" + dynamicSql + "</select>";XPathParser parser = new XPathParser(xml);List<XNode> xNodes = parser.evalNodes("select|insert|update|delete");BoundSql boundSql = null;if (xNodes != null && xNodes.size() != 0) {if (xNodes.size() > 1) {throw new RuntimeException("只能解析一句sql");} else {LanguageDriver langDriver = configuration.getLanguageDriver((Class)null);XNode node = (XNode)xNodes.get(0);SqlSource sqlSource = langDriver.createSqlSource(configuration, node, (Class)null);boundSql = sqlSource.getBoundSql(params);}} else {throw new RuntimeException("找不到sql语句");}// 获取SQL并替换参数return replaceParameters(boundSql, params,boundSql.getSql().substring(0,boundSql.getSql().indexOf(" ")));}/*** 使用ParameterHandler替换参数* @param boundSql* @param params* @param queryMethod 查询方式 select/delete...* @return* @throws SQLException*/private String replaceParameters(BoundSql boundSql, Map<String, Object> params,String queryMethod) throws SQLException {//  获取配置和MappedStatementConfiguration configuration = sqlSessionFactory.getConfiguration();MappedStatement mappedStatement = configuration.getMappedStatement("cn.com.fssg.platform.modules.engine.mapper.DynamicMapper.executeDynamicSql");// 创建ParameterHandlerParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, params, boundSql);Connection connection = configuration.getEnvironment().getDataSource().getConnection();PreparedStatement ps = connection.prepareStatement(boundSql.getSql());parameterHandler.setParameters(ps);// 获取PreparedStatement的最终SQL,这里PreparedStatement已经注入了参数String preparedSql = ps.toString();// 去掉PreparedStatement前缀,保留实际的SQL部分,假设SQL是从select开始int sqlIndex = preparedSql.indexOf(queryMethod);return preparedSql.substring(sqlIndex);}}

http://www.ppmy.cn/news/1541060.html

相关文章

R语言绘制Venn图(文氏图、温氏图、维恩图、范氏图、韦恩图)

Venn图&#xff0c;又称文氏图&#xff0c;标题中其他名字也是它的别称&#xff0c;由封闭圆形组成&#xff0c;代表不同集合。圆形重叠部分表示集合交集&#xff0c;非重叠处为独有元素。在生物学、统计学等领域广泛应用&#xff0c;可展示不同数据集相似性与差异&#xff0c;…

企业电子印章主要通过以下几种方式进行防伪

企业电子印章主要通过以下几种方式进行防伪&#xff1a; 一、数字证书和加密技术 数字证书认证 企业电子印章依托数字证书&#xff0c;数字证书由权威的第三方数字认证机构颁发&#xff0c;确保了印章使用者的身份真实性。 数字证书如同企业在数字世界的身份证&#xff0c;包…

wpf grid 的用法

WPF中的Grid是一种布局控件&#xff0c;可用于将子控件按照行和列的方式排列。 以下是Grid控件的用法&#xff1a; 在XAML文件中&#xff0c;添加一个Grid控件&#xff1a; <Grid> </Grid>在Grid控件中&#xff0c;添加行和列定义&#xff1a; <Grid><…

Uptime Kuma: 全面的开源网站监控解决方案

在当今数字化时代,网站和服务的可用性对于企业和个人来说至关重要。Uptime Kuma作为一款功能强大的开源监控工具,为用户提供了全面的网站和服务监控解决方案。本文将深入介绍Uptime Kuma的特性、安装方法以及更新维护,帮助读者了解这一优秀的监控工具。 主要特性 Uptime Kuma…

dbt-codegen: dbt自动生成模板代码

dbt项目采用工程化思维&#xff0c;数据模型分层实现&#xff0c;支持描述模型文档和测试&#xff0c;非常适合大型数据工程项目。但也需要用户编写大量yaml描述文件&#xff0c;这个过程非常容易出错且无聊。主要表现&#xff1a; 手工为dbt模型编写yaml文件&#xff0c;这过…

【Golang】Go语言web框架Gin响应客户端有哪些方式

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

基于SpringBoot的旅游网站的设计与实现

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 系统展示 【2024最新】基于JavaSpringBootVueMySQL的&#xff0c;前后端分离。 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;…

HTTP和RPC通信协议

在软件开发中&#xff0c;通信协议扮演着关键的角色&#xff0c;它们定义了不同系统或组件之间进行通信的规则和方式。HTTP&#xff08;Hypertext Transfer Protocol&#xff09;和RPC&#xff08;Remote Procedure Call Protocol&#xff09;是两种常见的通信协议。然而RPC 和…