Java - 将 SQL 语句存储在外部文件中 [已关闭]

2022-08-31 22:23:52

我正在寻找一种将SQL语句存储在外部文件中的Java库/框架/技术。支持团队(包括 DBA)应该能够(稍微)更改语句,以便在数据库架构更改或进行调优时保持同步。

以下是要求:

  • 该文件必须可以从Java应用程序读取,但也必须可由支持团队编辑,而无需花哨的编辑器
  • 理想情况下,文件应为纯文本格式,但 XML 也可以
  • 允许存储/检索 DML 以及 DDL 语句
  • 可以在稍后阶段添加新语句(应用程序足够灵活,可以选取并执行它们)
  • 语句可以分组(并由应用程序作为一个组执行)
  • 语句应允许参数

笔记:

  • 检索后,语句将使用Spring的JDBCTemplate执行
  • 休眠或Spring的IOC容器将不会被使用

到目前为止,我设法找到了以下Java库,这些库使用外部文件来存储SQL语句。但是,我主要感兴趣的是存储,而不是隐藏所有JDBC“复杂性”的库。

  • Axamol SQL Library

    示例文件内容:

    <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>
    
  • 伊巴蒂斯

    示例文件内容:

    <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>
    
  • 网4J

    -- 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}
    }
    

任何人都可以推荐经过尝试和测试的解决方案吗?


答案 1

只需创建一个简单的 Java 属性文件,其中包含键值对,如下所示:

users.select.all = select * from user

在 DAO 类中声明属性类型的私有字段,并使用 Spring 配置注入它,该配置将从文件中读取值。

更新:如果要支持多行 SQL 语句,请使用以下表示法:

users.select.all.0 = select *
users.select.all.1 = from   user

答案 2

在这里粘贴我的答案 清洁方式 以外部化长 (+20 行 sql) 时使用 spring jdbc?

前段时间我遇到了同样的问题,并提出了YAML。它支持多行字符串属性值,因此您可以在查询文件中编写如下内容:

selectSomething: >
  SELECT column1, column2 FROM SOMETHING

insertSomething: >
  INSERT INTO SOMETHING(column1, column2)
  VALUES(1, '1')

这里,和是查询名称。所以它非常方便,并且包含很少的特殊字符。查询由空行分隔,并且每个查询文本必须缩进。请注意,查询绝对可以包含自己的缩进,因此以下内容是完全有效的:selectSomethinginsertSomething

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 文件映射到包含查询名称/字符串的映射。


推荐