Чистый способ экстернализации длинной (+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