我正在寻找一种在外部文件中存储SQL语句的Java库/框架/技术.支持团队(包括DBA)应该能够(略微)更改语句,以便在数据库架构更改或调整目的时保持它们同步.
以下是要求:
笔记:
到目前为止,我设法找到以下Java库,它们使用外部文件来存储SQL语句.但是,我主要对存储而不是隐藏所有JDBC"复杂性"的库感兴趣.
示例文件内容:
<s:query name="get_emp">
<s:param name="name" type="string"/>
<s:sql databases="oracle">
select *
from scott.emp
join scott.dept on (emp.deptno = dept.deptno)
where emp.ename = <s:bind param="name"/>
</s:sql>
</s:query>
Run Code Online (Sandbox Code Playgroud)示例文件内容:
<sqlMap namespace="Contact"">
<typeAlias alias="contact"
type="com.sample.contact.Contact"/">
<select id="getContact"
parameterClass="int" resultClass="contact"">
select CONTACTID as contactId,
FIRSTNAME as firstName,
LASTNAME as lastName from
ADMINISTRATOR.CONTACT where CONTACTID = #id#
</select>
</sqlMap>
<insert id="insertContact" parameterClass="contact">
INSERT INTO ADMINISTRATOR.CONTACT( CONTACTID,FIRSTNAME,LASTNAME)
VALUES(#contactId#,#firstName#,#lastName#);
</insert>
<update id="updateContact" parameterClass="contact">
update ADMINISTRATOR.CONTACT SET
FIRSTNAME=#firstName# ,
LASTNAME=#lastName#
where contactid=#contactId#
</update>
<delete id="deleteContact" parameterClass="int">
DELETE FROM ADMINISTRATOR.CONTACT WHERE CONTACTID=#contactId#
</delete>
Run Code Online (Sandbox Code Playgroud)-- This is a comment
ADD_MESSAGE {
INSERT INTO MyMessage -- another comment
(LoginName, Body, CreationDate)
-- another comment
VALUES (?,?,?)
}
-- Example of referring to a constant defined above.
FETCH_RECENT_MESSAGES {
SELECT
LoginName, Body, CreationDate
FROM MyMessage
ORDER BY Id DESC LIMIT ${num_messages_to_view}
}
Run Code Online (Sandbox Code Playgroud)任何人都可以推荐经过试验和测试的解决方案吗?
Bor*_*vić 58
只需创建一个简单的Java Properties文件,其中包含键值对,如下所示:
users.select.all = select * from user
Run Code Online (Sandbox Code Playgroud)
在DAO类中声明一个Properties类型的私有字段,并使用Spring配置将其注入,该配置将从文件中读取值.
更新:如果要支持多行的SQL语句,请使用以下表示法:
users.select.all.0 = select *
users.select.all.1 = from user
Run Code Online (Sandbox Code Playgroud)
如果必须这样做,您应该查看MyBatis项目.我没有用它,但已经多次听过它.
分离SQL和Java不是我最喜欢的方法,因为SQL实际上是代码,并且与调用它的Java代码紧密耦合.维护和调试分离的代码可能具有挑战性.
绝对不要使用存储过程.它们只应用于通过减少数据库和应用程序之间的流量来提高性能.
我们在面对这个问题时实现的一个简单解决方案是将SQL/DML外部化为文件(mySql.properties),然后使用MessageFormat.format(String [] args)将动态属性注入SQL.
例如:mySql.properties:
select *
from scott.emp
join scott.dept on (emp.deptno = dept.deptno)
where emp.ename = {0}
Run Code Online (Sandbox Code Playgroud)
实用方法:
public static String format(String template, Object[] args) {
String cleanedTemplate = replaceSingleQuotes(template);
MessageFormat mf = new MessageFormat(cleanedTemplate);
String output = mf.format(args);
return output;
}
private static String replaceSingleQuotes(String template) {
String cleaned = template.replace("'", "''");
return cleaned;
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
String sqlString = youStringReaderImpl("/path/to/file");
String parsedSql = format(sqlString, new String[] {"bob"});
Run Code Online (Sandbox Code Playgroud)
粘贴在这里我的答案,以清洁的方式来外部长(+20行SQL)使用了Spring JDBC是什么时候?:
我前段时间遇到了同样的问题,并想出了YAML.它支持多行字符串属性值,因此您可以在查询文件中编写类似这样的内容:
selectSomething: >
SELECT column1, column2 FROM SOMETHING
insertSomething: >
INSERT INTO SOMETHING(column1, column2)
VALUES(1, '1')
Run Code Online (Sandbox Code Playgroud)
在这里,selectSomething
并且insertSomething
是查询的名称.所以它非常方便,并且包含很少的特殊字符.查询由空行分隔,每个查询文本必须缩进.请注意,查询绝对可以包含自己的缩进,以便以下内容完全有效:
anotherSelect: <
SELECT column1 FROM SOMETHING
WHERE column2 IN (
SELECT * FROM SOMETHING_ELSE
)
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用以下代码在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!!!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,创建了映射映射,将每个YAML文件映射到包含查询名称/字符串的映射.
该ElSql库提供此功能.
ElSql由一个小的jar文件(六个公共类)组成,允许加载外部SQL文件(elsql).该文件使用简单格式来选择性地提供比仅加载文件更多的行为:
-- an example comment
@NAME(SelectBlogs)
@PAGING(:paging_offset,:paging_fetch)
SELECT @INCLUDE(CommonFields)
FROM blogs
WHERE id = :id
@AND(:date)
date > :date
@AND(:active)
active = :active
ORDER BY title, author
@NAME(CommonFields)
title, author, content
// Java code:
bundle.getSql("SelectBlogs", searchArgs);
Run Code Online (Sandbox Code Playgroud)
该文件被分解为@NAME
可以从代码引用的块.每个块由重要的空白缩进定义.@PAGING
将插入必要的分页代码,如FETCH/OFFSET.@AND
只有在指定的变量存在时才会输出(帮助构建动态搜索).DSL还处理搜索中的通配符LIKE
vs.=
可选DSL标记的目标是提供在尝试以数据库中立方式构建动态SQL时经常遇到的常见基础知识.
归档时间: |
|
查看次数: |
54695 次 |
最近记录: |