すべてのデータをロードせずに渡された 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