我想将我的应用程序中的一些大型查询外部化到 properties\sql\xml 文件。但是我想知道是否有人对如何以干净的方式实现这一点有一些建议。大多数结果建议使用 ORM 框架,但由于某些数据限制,这并不适用。
我看了一下:Java - 将 SQL 语句存储在外部文件中,但对一些查询执行这个属性名 .1、.2 等,这些查询每个都超过 20 行,看起来并不那么干净。
我想将我的应用程序中的一些大型查询外部化到 properties\sql\xml 文件。但是我想知道是否有人对如何以干净的方式实现这一点有一些建议。大多数结果建议使用 ORM 框架,但由于某些数据限制,这并不适用。
我看了一下:Java - 将 SQL 语句存储在外部文件中,但对一些查询执行这个属性名 .1、.2 等,这些查询每个都超过 20 行,看起来并不那么干净。
您可以将查询放在 xml 文件中
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="getPersonById">
<![CDATA[
Select Name From Person
Where Id =?
]]>
</entry>
<entry key="getPersonBySSN">
<![CDATA[
]]>
</entry>
</properties>
在 Spring 应用程序上下文中,加载此 xml 文件
<bean id="queryProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations" value="classpath:/queries.xml" />
</bean>
在你的 DAO 类中注入这个 bean
<bean id="myDAO" class="com.xyz.dao.MyDAOImpl">
<property name="queryProps" ref="queryProps" />
</bean>
在您的 DAO 类中定义 queryProps 并且不要忘记为此设置 setter 方法
private Properties queryProps;
现在您可以像这样在您的 DAO 中访问查询 -
String query = queryProps.getProperty("getPersonById");
希望这可以帮助。
前段时间我遇到了同样的问题,并提出了 YAML。它支持多行字符串属性值,因此您可以在查询文件中编写如下内容:
selectSomething: >
SELECT column1, column2 FROM SOMETHING
insertSomething: >
INSERT INTO SOMETHING(column1, column2)
VALUES(1, '1')
在这里,selectSomething
和insertSomething
是查询名称。所以它真的很方便,并且包含很少的特殊字符。查询以空行分隔,每个查询文本必须缩进。请注意,查询绝对可以包含自己的缩进,因此以下内容完全有效:
anotherSelect: <
SELECT column1 FROM SOMETHING
WHERE column2 IN (
SELECT * FROM SOMETHING_ELSE
)
然后,您可以在 SnakeYAML 库的帮助下,使用以下代码将文件的内容读入哈希映射:
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.FileUtils;
import java.io.FileReader;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.FileNotFoundException;
public class SQLReader {
private Map<String, Map> sqlQueries = new HashMap<String, Map>();
private SQLReader() {
try {
final File sqlYmlDir = new File("dir_with_yml_files");
Collection<File> ymlFiles = FileUtils.listFiles(sqlYmlDir, new String[]{"yml"}, false);
for (File f : ymlFiles) {
final String fileName = FilenameUtils.getBaseName(f.getName());
Map ymlQueries = (Map)new Yaml().load(new FileReader(f));
sqlQueries.put(fileName, ymlQueries);
}
}
catch (FileNotFoundException ex) {
System.out.println("File not found!!!");
}
}
}
在上面的示例中,创建了一个映射映射,将每个 YAML 文件映射到一个包含查询名称/字符串的映射。
这是对Pankaj 回答的补充。这个在属性 XML 中没有 CDATA 并使用自动装配。我必须将此添加为答案,因为如果我必须在评论部分执行此操作,我将无法格式化代码。
确保在 spring 应用程序上下文 xml 文件中有以下命名空间。
xmlns:util="http://www.springframework.org/schema/util
将以下 bean 添加到 spring 应用程序上下文 xml
<util:properties id="sqls" location="classpath:oracle/sqls.xml" />
该文件的内容sqls.xml
是
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Employee Queries</comment>
<entry key="employee.insert">
INSERT
INTO EMPLOYEE
(
ID,
NAME,
AGE,
DEPARTMENT
)
VALUES
(
EMPLOYEE_SEQ.NEXTVAL,
?,
?,
?
)
</entry>
</properties>
自动装配属性如下
@Autowired
@Qualifier("sqls")
private Properties sqls;
从属性获取 sql 查询的代码
String sql = sqls.getProperty("employee.insert");
您可以通过在行尾放置 \ 来在属性文件中执行多行查询。例如
queries.myquery = select \
foo, bar \
from mytable \
where baz > 10
在JdbcTestUtils 和方法“executeSqlScript”和“readScript”中获取战利品。