2

すべてのデータをロードせずに渡された HQL に基づいて合計レコード数を取得するための util 関数を作成しています。HQL で渡されたものは、多くの選択、結合、場所条件、グループ化、および並べ替えでかなり複雑になる場合があります。そのために、クエリをSELECT COUNT(*) FROM (<ORIGINAL_QUERY>) x. Hibernate では FROM 要素でのサブクエリが許可されていないため、これは HQL では不可能であることがわかりました。今、いくつかの名前付きパラメーター (いくつかは単純なパラメーターであり、いくつかはリストである可能性があります) を持つ可能性があるこのランダムな 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:111) で org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97) で org.hibernate.engine.jdbc org.hibernate.loader.Loader.getResultSet(Loader.java:2313) の .internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79) 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) org.hibernate.loader.Loader.doList(Loader.java:2813) org.hibernate.loader.Loader.doList(Loader.java:2796) 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) ) 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) 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) 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)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) 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)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: エラー: 演算子が存在しません: integer = bytea ヒント: 指定された名前と引数の型に一致する演算子はありません。明示的な型キャストを追加する必要がある場合があります。位置: 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) org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441) org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365) org.postgresql.jdbc .PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:155) org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:118) org.hibernate.engine.jdbc.

環境:

  • Java 8
  • 休止状態 5.1.8
  • Postgres-JDBC 42.2.2
  • PostgreSQL サーバー 10.5
4

2 に答える 2

0

HQL ではクエリ パラメータを使用し、setParameterList メソッドで Collection を設定できます。

Query q = session.createQuery("SELECT entity FROM Entity entity WHERE name IN (:names)");
q.setParameterList("names", names);
于 2018-08-13T07:17:39.847 に答える