背景
最近遇到一个需求, 框架需要执行用户给定的SQL
语句,该SQL
语句内包含占位符, 占位符表示的内容存在于在框架中,比如下面的sql
select * from xxx where id = ${xxid}
xxid
值存在于框架中,也就是说框架需要解析用户设置的sql
,将占位符用框架内的值替换。
众所周知,Mybatis
能够解析占位符,执行SQL
语句, 但是由于sql
语句由用户传入,不是写在xml
或Mybatis
的注解中,查阅了Mybatis
文档,其并不支持直接执行sql
语句, 所以必须考虑如何解析占位符的问题。
解决方法
Freemarker
可以基于模板生成输出文本,并且其要求的dataModel
是Object
类型,只要sql
语句的占位符名字存在于dataModel
中,就能够将占位符替换为具体的值。占位符需要使用${}
修饰。
注意点: 使用Freemarker API
,上下文里占位符对应的值如果为Null
,会抛出一个异常。
具体操作
Configuration cfg = new Configuration(Configuration.VERSION_2_3_26);
cfg.setDefaultEncoding("UTF-8");
cfg.setNumberFormat("computer");
- 设置编码格式
- 设置
number
的格式,这一步比较重要,因为Freemarker
解析出来的整数是每3
位带逗号的,也就会导致sql
执行失败。computer
格式相当于Freemarker
模板语法的c
,即someNumber?c
,这样解析出来的整数是不带逗号的。
Template template = new Template("tempTest", YourStr, cfg);
- 获取模板,第一个参数为模板名,第二个参数为需要解析的字符串,第三个参数为配置
Writer out = new StringWriter();
template.process(dataModel, out);
out.toString();
dataModel
存在和占位符同名的变量process()
方法进行解析,同时将结果写入out
,最后执行out.toString()
就可以获得解析后的字符串
第一次接触到Freemarker
,感觉非常好用,尤其是它的dataModel
是可以多层嵌套的,只要字符串内占位符对应的名称对应。