前言
我们在使用 JDBC 时, 如果把所有的 SQL 语句全写在 Java 文件中, 由于 Java 不支持 Here Document, 多行字符串要么用加号, 要么用 Java 8 的 String.join()方法来连接, 同时不能对 SQL 语句进行语法加亮, 所以这样的 SQL 字符串阅读性很差. 别说为何不用 Hibernate 之类的而不直接写原始的 SQL 语句, 在操作复杂的系统时还是会用到 JdbcTemplate 吧.
所以我们希望能把 SQL 语句写在单独的 *.sql 文件里, 这样很多编辑器就能语法高亮显示, 或在输入时还能得到智能提示.
有种办法是把 *.sql 用作为属性文件, 那么在其中定义多行的 SQL 语句时就得这样
?
加载后就能用 getProperty("select.user")来引用相应的语句了. 属性文件的换行与 Bash 一样, 也是用 \, 但如此, 则 *.sql 并非一个纯粹的 SQL 文件, 不能正确的进行语法加亮, 一旦写上 SQL 的注释 -- 就更是在添乱了.
所以我们的第二个方案是: 首先 *.sql 就该是一个真正的 SQL 文件, 而不是伪装的属性文件, 为了能在程序中引用每一条 SQL 语句, 我们该如何表示各自的 Key 呢? 这里的灵感仍然是来自于 Linux Shell, 在 Linux Shell 中指定执行环境的用了特殊的注释方式 #!, 如
?
依葫芦画瓢, SQL 的标准单注释是 --, 因而我们也创建一个特别的注释 --!, , 其后的字符串就是接下来 SQL 语句的 Key.
举例如下
?
--! 之后是 key select.user, 往下在未到文件结束, 或是遇到下一个 --! 之前就是这个 key 对应的完整 SQL 语句的内容.
本文以 Spring 项目为例来演示如何应这个 SQL 文件, 其实在其他类型的 Java 项目中同样可以借鉴.
因为这是一个真正的 SQL 文件, 所以在 Spring 中我们无法直接作为属性文件来加载. 假设我们把该文件存储为 src/resources/sql/queries.sql, 因此我们不能直接用
?
加载该文件.
幸好 PropertySource 注解还有一个属性 factory, 类型为 PropertySourceFactory, 这就是我们作文章的地方, 马上着手自定义一个 SqlPropertySourceFactory, 在其中总有办法把一个 *.sql 的内容转换为 Properties. 因此将来我们要加载 sql/queries.sql 文件所用的注解形式就会是
?
接下来就是本文的关键, 看看 SqlPropertySourceFactory 的实现
SqlPropertySourceFactory.java
?
我们定义的 src/resources/sql/queries.sql 文件内容如下:
?
最后是如何应用它, 我们以 SpringBoot 的方式来启动一个 Spring 项目
DemoApplication.java
?
既然已转换为普通的属性了, 所以可以通过表达式 ${key}或 env.getProperty("key")来引用它们.
执行上面的代码, 输出如下:
?
就这么简单. 当然那个 *.sql 文件最好是写得严谨一些, 我们可以将来对 SqlPropertySourceFactory 进行逐步完善以应对更多的可能. 不管怎么说它是一个真正的 SQL 文件, 在代码中也能像任何别的属性那么方便的引用其中定义的 SQL 语句了.
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
原文链接:http://unmi.cc/spring-external-sql-statements/