• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Spring项目里将SQL语句写在.sql文件中的方法

java 搞代码 4年前 (2022-01-05) 52次浏览 已收录 0个评论

这篇文章主要介绍了Spring项目里如何将SQL语句写在.sql文件中的方法,文中给出了详细的介绍和示例代码,相信对大家的学习或者工作具有一定的参考借鉴价值,有需要的朋友们下面来一起看看吧。

前言

我们在使用 JDBC 时, 如果把所有的 SQL 语句全写在 Java 文件中, 由于 Java 不支持 Here Document, 多行字符串要么用加号, 要么用 Java 8 的 String.join() 方法来连接, 同时不能对 SQL 语句进行语法加亮, 所以这样的 SQL 字符串阅读性很差. 别说为何不用 Hibernate 之类的而不直接写原始的 SQL 语句, 在操作复杂的系统时还是会用到 JdbcTemplate 吧.

所以我们希望能把 SQL 语句写在单独的 *.sql 文件里, 这样很多编辑器就能语法高亮显示, 或在输入时还能得到智能提示.

 有种办法是把 *.sql 用作为属性文件, 那么在其中定义多行的 SQL 语句时就得这样

 select.user=select id, firstname, lastname, address \ from users \ where id=?

加载后就能用 getProperty("select.user") 来引用相应的语句了. 属性文件的换行与 Bash  一样, 也是用  \, 但如此, 则 *.sql 并非一个纯粹的 SQL 文件, 不能正确的进行语法加亮, 一旦写上 SQL 的注释 — 就更是在添乱了.

所以我们的第二个方案是: 首先 *.sql 就该是一个真正的  SQL 文件, 而不是伪装的属性文件, 为了能在程序中引用每一条 SQL 语句, 我们该如何表示各自的 Key 呢? 这里的灵感仍然是来自于 Linux Shell, 在 Linux Shell 中指定执行环境的用了特殊的注释方式 #!, 如

 #!/bin/bash #!/usr/bin/env python

依葫芦画瓢, SQL 的标准单注释是 –, 因而我们也创建一个特别的注释 –!, , 其后的字符串就是接下来 SQL 语句的 Key.

举例如下

 --!select.user select id, firstname, lastname, address from users where id=? --!update.user update ........

–! 之后是 key select.user, 往下在未到文件结束, 或是遇到下一个 –! 之前就是这个 key 对应的完整 SQL 语句的内容.

本文以 Spring 项目为例来演示如何应这个 SQL 文件, 其实在其他类型的 Java 项目中同样可以借鉴.

因为这是一个真正的 SQL 文件, 所以在 Spring 中我们无法直接作为属性文件来加载. 假设我们把该文件存储为 src/resources/sql/queries.sql, 因此我们不能直接用

 @PropertySource(value = "classpath:sql/queries.sql") public class AppConfig { ...... }

加载该文件.

幸好 PropertySource 注解还有一个属性 factory, 类型为 PropertySourceFactory, 这就是我们作文章的地方, 马上着手自定义一个 SqlPropertySourceFactory, 在其中总有办法把一个 *.sql 的内容转换为 Properties. 因此将来我们要加载  sql/queries.sql 文件所用的注解形式就会是

 @PropertySource(value = "classpath:sql/queries.sql", factory = SqlPropertySourceFactory.class) public class AppConfig { ......}

接下来就是本文的关键, 看看 SqlPropertySourceFactory 的实现

SqlPropertySourceFactory.java

 package cc.unmi; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; import java.io.BufferedReader; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; public class SqlPropertySourceFactory implements PropertySourceFactory { private static final String KEY_LEADING = "--!"; @Override public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException { Deque queries = new LinkedList(); new BufferedReader(resource.getReader()).lines().forEach(line -> { if (line.startsWith(KEY_LEADING)) { queries.addLast(new Pair(line.replaceFirst(KEY_LEADING, ""))); } else if (line.startsWith("--")) { //skip comment line } else if (!line.trim().isEmpty()) { Optional.ofNullable(queries.getLast()).ifPresent(pair -> pair.lines.add(line)); } }); Map sqlMap = queries.stream() .filter(pair -> !pair.lines.isEmpty()) .collect(Collectors.toMap(pair -> pair.key, pair -> String.join(System.lineSeparator(), pair.lines), (r, p<div style="color:transparent">来源gaodai.ma#com搞##代!^码网</div>air) -> r, LinkedHashMap::new)); System.out.println("Configured SQL statements:"); sqlMap.forEach((s, o) -> System.out.println(s + "=" + o)); return new MapPropertySource(resource.toString(), sqlMap); } private static class Pair { private String key; private List lines = new LinkedList(); Pair(String key) { this.key = key; } } }

我们定义的 src/resources/sql/queries.sql 文件内容如下:

 --external queries in this file --!select_users_by_id select id, firstname, lastname, address from users where id=? --!add_user insert users(id, firstname, lastname, address) values(DEFAULT, ?, ?, ?) -- --!no_statement --- --!update update users set firstname=? where id=?

最后是如何应用它, 我们以 SpringBoot 的方式来启动一个 Spring 项目

DemoApplication.java

 package cc.unmi; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; @SpringBootApplication @PropertySource(value = "classpath:sql/queries.sql", factory = SqlPropertySourceFactory.class) public class DemoApplication implements EnvironmentAware { private Environment env; @Value("${add_user}") private String sqlAddUser; @Bean public String testBean() { System.out.println("SQL_1:" + env.getProperty("select_users_by_id")); System.out.println("SQL_2:" + sqlAddUser); return "testBean"; } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Override public void setEnvironment(Environment environment) { env = environment; } }

既然已转换为普通的属性了, 所以可以通过表达式 ${key} env.getProperty("key") 来引用它们.

执行上面的代码, 输出如下:

 Configured SQL statements: select_users_by_id=select id, firstname, lastname, address from users where id=? add_user=insert users(id, firstname, lastname, address) values(DEFAULT, ?, ?, ?) update=update users set firstname=? where id=? SQL_1:select id, firstname, lastname, address from users where id=? SQL_2:insert users(id, firstname, lastname, address) values(DEFAULT, ?, ?, ?)

就这么简单. 当然那个 *.sql 文件最好是写得严谨一些, 我们可以将来对 SqlPropertySourceFactory 进行逐步完善以应对更多的可能. 不管怎么说它是一个真正的 SQL 文件, 在代码中也能像任何别的属性那么方便的引用其中定义的  SQL 语句了.

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

以上就是Spring项目里将SQL语句写在.sql文件中的方法的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Spring项目里将SQL语句写在.sql文件中的方法

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址