我正在编写一个实用函数来根据我传入的任何 HQL 获取总记录数,而无需加载所有数据。传入的 HQL 可能非常复杂,有很多选择、连接、条件、分组和排序。为此,我想用SELECT COUNT(*) FROM (<ORIGINAL_QUERY>) x
. 我发现,这对于 HQL 是不可能的,因为 Hibernate 不允许 FROM 元素中的子查询。现在,我正在尝试将这个可能具有一些命名参数(其中一些可能是简单参数,一些可能是列表)的随机 HQL 查询转换为可执行的 SQL 语句,而无需内联参数值。这似乎适用于简单参数,但不适用于列表参数。
hqlString 和 namedParameterMap 来自外部某处:
final String hqlString = "...";
final Map<String, Object> namedParametersMap = ...;
将 HQL 转换为 SQL 的代码(和 ParameterTranslations:
final QueryTranslatorFactory translatorFactory = new ASTQueryTranslatorFactory();
final SessionFactoryImplementor factory = getSessionFactory();
final QueryTranslator translator = translatorFactory.createQueryTranslator(hqlString, hqlString, Collections.EMPTY_MAP, factory, null);
translator.compile(Collections.EMPTY_MAP, false);
final String sqlString = translator.getSQLString();
final ParameterTranslations parameterTranslations = translator.getParameterTranslations());
创建 SQLQuery、设置参数并执行查询的代码:
SQLQuery sqlQuery = getCurrentSession().createSQLQuery(sqlString);
((Set<?>) parameterTranslations.getNamedParameterNames()).forEach(parameterName -> {
for (int position : parameterTranslations.getNamedParameterSqlLocations(parameterName)) {
sqlQuery.setParameter(position, namedParametersMap.get(parameterName));
}
});
final Long rowCount = ((BigInteger) query.uniqueResult()).longValueExact();
此查询按预期工作:
final String hqlString = "SELECT p.firstname, p.surname FROM Person p WHERE p.id = :param1";
final Map<String, Object> namedParametersMap = Maps.newHashMap(ImmutableMap.<String, Object>of("param1", Integer.valueOf(1));
此查询不起作用:
String hqlString = "SELECT p.firstname, p.surname FROM Person p WHERE p.id IN (:param1)";
final Map<String, Object> namedParametersMap = Maps.newHashMap(ImmutableMap.<String, Object>of("param1", Lists.newArrayList(Integer.valueOf(1)));
例外:
org.hibernate.exception.SQLGrammarException:无法在 org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) 的 org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106) 处提取 ResultSet在 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97) 在 org.hibernate.engine.jdbc 的 org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) .internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79) 在 org.hibernate.loader.Loader.getResultSet(Loader.java:2313) 在 org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2096) 在 org. hibernate.loader.Loader.executeQueryStatement(Loader.java:2072) at org.hibernate.loader.Loader.doQuery(Loader.java:941) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:352) at org.hibernate.loader.Loader.doList(Loader.java:2813) at org.hibernate.loader.Loader.doList(Loader.java:2796) at org .hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2625) 在 org.hibernate.loader.Loader.list(Loader.java:2620) 在 org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:322 ) 在 org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1996) 在 org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322) 在 org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java: 125) 在 org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) 在 HQLQueryUtils.getCount(HQLQueryUtils.java:350)352) 在 org.hibernate.loader.Loader.doList(Loader.java:2813) 在 org.hibernate.loader.Loader.doList(Loader.java:2796) 在 org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java :2625) org.hibernate.loader.Loader.list(Loader.java:2620) org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:322) org.hibernate.internal.SessionImpl.listCustomQuery( SessionImpl.java:1996) 在 org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322) 在 org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) 在 org.hibernate.internal.AbstractQueryImpl.uniqueResult (AbstractQueryImpl.java:966) 在 HQLQueryUtils.getCount(HQLQueryUtils.java:350)352) 在 org.hibernate.loader.Loader.doList(Loader.java:2813) 在 org.hibernate.loader.Loader.doList(Loader.java:2796) 在 org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java :2625) org.hibernate.loader.Loader.list(Loader.java:2620) org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:322) org.hibernate.internal.SessionImpl.listCustomQuery( SessionImpl.java:1996) 在 org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322) 在 org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) 在 org.hibernate.internal.AbstractQueryImpl.uniqueResult (AbstractQueryImpl.java:966) 在 HQLQueryUtils.getCount(HQLQueryUtils.java:350)listIgnoreQueryCache(Loader.java:2625) at org.hibernate.loader.Loader.list(Loader.java:2620) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:322) at org.hibernate.internal .SessionImpl.listCustomQuery(SessionImpl.java:1996) 在 org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322) 在 org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) 在 org.hibernate。 internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) 在 HQLQueryUtils.getCount(HQLQueryUtils.java:350)listIgnoreQueryCache(Loader.java:2625) at org.hibernate.loader.Loader.list(Loader.java:2620) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:322) at org.hibernate.internal .SessionImpl.listCustomQuery(SessionImpl.java:1996) 在 org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322) 在 org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) 在 org.hibernate。 internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) 在 HQLQueryUtils.getCount(HQLQueryUtils.java:350)322) 在 org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) 在 org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) 在 HQLQueryUtils.getCount(HQLQueryUtils.java:350)322) 在 org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) 在 org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) 在 HQLQueryUtils.getCount(HQLQueryUtils.java:350)
原因:org.postgresql.util.PSQLException:错误:运算符不存在:整数 = bytea 提示:没有运算符与给定名称和参数类型匹配。您可能需要添加显式类型转换。位置: org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2178) org.postgresql.core.v3 的 org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2433) 的 301。在 org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441) 在 org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365) 在 org.postgresql.jdbc 的 QueryExecutorImpl.execute(QueryExecutorImpl.java:306) .PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:155) 在 org.hibernate.engine.jdbc 的 org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:118)。
环境:
- 爪哇 8
- 休眠 5.1.8
- Postgres-JDBC 42.2.2
- PostgreSQL 服务器 10.5