使用列表参数

时间:2018-08-13 06:46:20

标签: java postgresql hibernate hql jdbc-postgres

我正在编写一个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的代码(以及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)的org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)处提取ResultSet :42)在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)在org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)在org.hibernate。 org.hibernate.loader.Loader.getResultSet(Loader.java:2313)位于org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2096)处的engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79)位于org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2072)位于org.hibernate.loader.Loader.doQuery(Loader.java:941)位于org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java: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.internal.SessionImpl.listCustomQuery(SessionImpl.java:1996)于org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1996)于org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl。 org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125)处的org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966)处的HQLQueryUtils.getCount(HQLQueryUtils.java:350)< / p>

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

  

环境:

     
      
  • Java 8
  •   
  • 休眠5.1.8
  •   
  • Postgres-JDBC 42.2.2
  •   
  • PostgreSQL服务器10.5
  •   

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

您可以使用直接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);
            }

假设Yourclass有两个元素日期和金额