Я использую hibernate, чтобы сделать приложение независимым от любой СУБД. В некоторых частях приложения мне нужно объединить идентификаторы связанной таблицы с group_concat, list_agg или string_agg.
Я улучшил спящие диалекты, чтобы отобразить функцию hql (group_concat) с любым из эквивалентов на любых используемых мной дБмах. string_agg в postgresql, list_agg в oracle.
Проблема возникает из-за того, что в SQL Server <2017 нет такой функции, как group_concat, и требуется выполнить sql в select для проецирования результата в виде поля. </p>
ListAGG в SQLSERVER
PostgreSQL
this.registerFunction("group_concat", new SQLFunctionTemplate(StandardBasicTypes.STRING, "STRING_AGG(?1 || '', ?2)"));
SQL Server
this.registerFunction("group_concat", new SQLFunctionTemplate(StandardBasicTypes.STRING, "STUFF( (?3 FOR XML PATH ('') ), 1, 1, '')"));
Мой основной подход состоял в том, чтобы разрешить новый 3-й параметр в hql group_concat для получения прямого sql для выполнения в случае SQL Server, который я ранее писал на HQL, и компиляции в SQL.
protected String translateHqlToSql(String paramSql) {
ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
SessionImplementor hibernateSession = this.em.unwrap(SessionImplementor.class);
QueryTranslator queryTranslator = queryTranslatorFactory.createQueryTranslator("", paramSql, java.util.Collections.EMPTY_MAP, hibernateSession.getFactory(), null);
Map<String,String> replacements = new HashMap<>();
queryTranslator.compile(replacements, false);
return queryTranslator.getSQLString();
}
fallBackQuery = this.translateHqlToSql("SELECT a.id, "
+ "FROM Clients d "
+ "left join d.addresses a "
+ "WHERE d.id = c.id");
SELECT c.id, group_concat(a.id, ',', fallBackQuery)
FROM Clients c left join c.addresses a
Я ожидал получить следующие SQL
PostgreSQL
SELECT c.id, STRING_AGG(a.ID, ',')
FROM TB_CLIENT c
LEFT JOIN TB_ADDRESS a ON a.FK_CLIENT = c.ID
SQLServer 2012
SELECT c.id,
STUFF(
(SELECT a.ID
FROM TB_CLIENT d
LEFT JOIN TB_ADDRESS a ON a.FK_CLIENT = d.ID
WHERE d.ID = a.ID
FOR XML PATH),
1, 1, '')
FROM TB_CLIENT c
LEFT JOIN TB_ADDRESS a ON a.FK_CLIENT = c.ID
Проблема начинается с fallBackQuery, так как мне нужно скомпилировать hql, зависящий от другого.
WHERE d.ID = a.ID
Возможно, у меня совершенно неправильный подход.
Спасибо, любая помощь приветствуется