将 HQL 查询转换为带有列表参数的可执行 SQL 查询



我正在编写一个 util 函数,以根据我在不加载所有数据的情况下传入的任何 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(和参数翻译:

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: 无法提取 ResultSet at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106( at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42( at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111( at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97( at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79( at org.hibernate.loader.Loader.getResultSet(Loader.java:2313( at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2096( at 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( 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( at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322( at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125( at org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966( at HQLQueryUtils.getCount(HQLQueryUtils.java:350(

由以下原因引起:org.postgresql.util.PSQLException:错误:运算符不存在:整数 = bytea 提示:没有运算符与给定的名称和参数类型匹配。 可能需要添加显式类型强制转换。 Position: 301 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2433( at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2178( at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:306( at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441( at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365( at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:155( at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:118( at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70( ...49 更多

环境:

  • 爪哇 8
  • 休眠 5.1.8
  • Postgres-JDBC 42.2.2
  • PostgreSQL Server 10.5

在 HQL 中,您可以使用查询参数并使用 setParameterList 方法设置集合。

Query q = session.createQuery("SELECT entity FROM Entity entity WHERE name IN (:names)");
q.setParameterList("names", names);

你可以使用直接 sql

String sql="your query"
Query query = sessionFactory.getCurrentSession().createSQLQuery(sql);
query.setParameter("paramterName", parameterValue);
List<Object[]> resultSet = query.list();
List<YouClass > data= new ArrayList<>();
for (Object[] row : resultSet) {
YouClass yourObject=new YouClass ();
yourObject.setDate((Date) row[0]);
yourObject.setAmount((BigDecimal) row[1]);
data.add(yourObject);
}

假设您的类有两个元素日期和数量

最新更新