我使用休眠是为了使应用程序独立于任何DBMS,在应用程序的某些部分中,我需要使用group_concat,list_agg或string_agg来聚合相关表的ID。
我已经增强了休眠方言,以将hql函数(group_concat)与我正在使用的任何dbms上的任何等效项进行映射。将string_agg转换为postgresql,将list_agg转换为oracle。
问题变得存在,因为在SQL Server <2017中没有像group_concat这样的功能,并且需要在select中执行sql才能将结果投影为字段。
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, '')"));
我的主要方法是在hql group_concat中允许一个新的第3个参数,以便在我以前用HQL编写并编译为SQL的SQL Server中接收直接执行的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
可能我得到了一个完全错误的方法。
谢谢您的帮助,