Чистый способ экстернализации длинной (+20 строк sql) при использовании spring jdbc?

Я хочу экстренно выделить некоторые большие запросы в моем приложении в свойствах \sql\xml файлов. Однако мне было интересно, есть ли у кого-то рекомендации относительно того, как это сделать чистым способом. Большинство результатов рекомендуют использовать структуру ORM, но это не применимо из-за некоторых ограничений данных.

Я взглянул на: Java - сохранение SQL-операторов во внешнем файле, но делая это имя свойства .1,.2 и т.д. для нескольких запросов, каждый из которых длиннее что 20 строк не кажутся чистыми.

Ответ 1

Вы можете поместить свои запросы в 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 приложении Context загрузите этот XML файл

<bean id="queryProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations" value="classpath:/queries.xml" />
</bean>

Ввести этот bean в свой класс DAO

<bean id="myDAO" class="com.xyz.dao.MyDAOImpl">
  <property name="queryProps" ref="queryProps" />
</bean>

Определите queryProps в вашем классе DAO и не забудьте установить метод настройки для этого

 private Properties queryProps;

Теперь вы можете получить доступ к запросу в своем DAO, как это -

 String query = queryProps.getProperty("getPersonById");

Надеюсь, что это поможет.

Ответ 2

Я столкнулся с той же проблемой некоторое время назад и придумал 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 с картой, содержащей имена/строки запросов.

Ответ 3

Это в дополнение к тому, что ответил Панкадж. У этого нет CDATA в XML-свойствах и используется аутоавто. Я должен был добавить это как ответ, поскольку я не могу форматировать код, если бы мне пришлось это сделать в разделе комментариев.

Убедитесь, что у вас есть следующее пространство имен в xml файле контекста приложения spring.

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");

Ответ 4

Возьмите добычу в JdbcTestUtils и методы "executeSqlScript" и "readScript".

Ответ 5

Вы можете делать многострочные запросы в файле свойств, помещая\в конец строки. Например

queries.myquery = select \
foo, bar \
from mytable \
where baz > 10