Hibernate-reactive: MS SQLServerおよびHibernateReactive1.0.0.CR9で結果を制限する際のパラメーター置換エラー

作成日 2021年08月05日  ·  13コメント  ·  ソース: hibernate/hibernate-reactive

こんにちは、ページングまたは範囲を使用しているときに1.0.0.CR9のMS SQLクエリパラメーターで問題が発生しています(SQL例外、メッセージ= ''? '。'の近くの構文が正しくありません)。おそらくパラメーターがSelect句にあるためですか?

スタック:Quarkus 2.1.0.Final / Panache Reactive / Mutiny 4.1.2 / Hibernate Reactive 1.0.0.CR9 / Hibernate Core 5.5.5.Final

私の残りのリソースから、これを実行します:
[PanacheRepository].find("firstName LIKE ?1").page(Page.of(25)).list();

HibernateでSQLがログオンしている場合、これは生成されたSQLです。

Hibernate:
    select
        top(?) request0_.id as id1_1_,
        request0_.caseId as caseid2_1_,
        request0_.caseNumber as casenumb3_1_,
        request0_.expires as expires4_1_,
        request0_.addressLine1 as addressl5_1_,
        request0_.addressLine2 as addressl6_1_,
        request0_.agency as agency7_1_,
        request0_.city as city8_1_,
        request0_.email as email9_1_,
        request0_.firstName as firstna10_1_,
        request0_.lastName as lastnam11_1_,
        request0_.phone as phone12_1_,
        request0_.relationship as relatio13_1_,
        request0_.state as state14_1_,
        request0_.zipcode as zipcode15_1_,
        request0_.submitted as submitt16_1_
    from
        Request request0_
    where
        request0_.firstName like <strong i="11">@P1</strong>

where句の正しいパラメータ置換に注意してください。ただし、select句の「top(?)」の置換は行われませんでした。
ページングを削除して再実行すると、クエリは正常に実行されます。

以下に示すトレースログ。HQLとSQLを示しています。 PanacheはクエリでsetMaxResults()を使用していると思います。 問題が発生している場合は、QuarkusまたはMutinyで問題を開いてください。よろしくお願いします!

2021-08-05 12:55:57,342 DEBUG [org.hib.hql.int.ast.QueryTranslatorImpl] (vert.x-eventloop-thread-1) HQL: FROM myproject.entities.Request WHERE requestor.firstName LIKE ?1
2021-08-05 12:55:57,342 DEBUG [org.hib.hql.int.ast.QueryTranslatorImpl] (vert.x-eventloop-thread-1) SQL: select request0_.id as id1_1_, request0_.caseId as caseid2_1_, request0_.caseNumber as casenumb3_1_, request0_.expires as expires4_1_, request0_.addressLine1 as addressl5_1_, request0_.addressLine2 as addressl6_1_, request0_.agency as agency7_1_, request0_.city as city8_1_, request0_.email as email9_1_, request0_.firstName as firstna10_1_, request0_.lastName as lastnam11_1_, request0_.phone as phone12_1_, request0_.relationship as relatio13_1_, request0_.state as state14_1_, request0_.zipcode as zipcode15_1_, request0_.submitted as submitt16_1_ from Request request0_ where request0_.firstName like ?
2021-08-05 12:55:57,342 DEBUG [org.hib.hql.int.ast.ErrorTracker] (vert.x-eventloop-thread-1) throwQueryException() : no errors
2021-08-05 12:55:57,342 TRACE [org.hib.rea.ses.imp.ReactiveHQLQueryPlan] (vert.x-eventloop-thread-1) Find: FROM myproject.entities.Request WHERE requestor.firstName LIKE ?1
2021-08-05 12:55:57,344 TRACE [org.hib.eng.spi.QueryParameters] (vert.x-eventloop-thread-1) Named parameters: {1=%j%}
2021-08-05 12:55:57,345 TRACE [org.hib.typ.des.sql.BasicBinder] (vert.x-eventloop-thread-1) binding parameter [2] as [VARCHAR] - [%j%]
2021-08-05 12:55:57,345 TRACE [org.hib.loa.Loader] (vert.x-eventloop-thread-1) Bound [3] parameters total
2021-08-05 12:55:57,355 DEBUG [org.hib.SQL] (vert.x-eventloop-thread-1)
    select
        top(?) request0_.id as id1_1_,
        request0_.caseId as caseid2_1_,
        request0_.caseNumber as casenumb3_1_,
        request0_.expires as expires4_1_,
        request0_.addressLine1 as addressl5_1_,
        request0_.addressLine2 as addressl6_1_,
        request0_.agency as agency7_1_,
        request0_.city as city8_1_,
        request0_.email as email9_1_,
        request0_.firstName as firstna10_1_,
        request0_.lastName as lastnam11_1_,
        request0_.phone as phone12_1_,
        request0_.relationship as relatio13_1_,
        request0_.state as state14_1_,
        request0_.zipcode as zipcode15_1_,
        request0_.submitted as submitt16_1_
    from
        Request request0_
    where
        request0_.firstName like <strong i="18">@P1</strong>
2021-08-05 12:55:57,358 ERROR [org.hib.rea.errors] (vert.x-eventloop-thread-1) HR000057: Failed to execute statement [$1select request0_.id as id1_1_, request0_.caseId as caseid2_1_, request0_.caseNumber as casenumb3_1_, request0_.expires as expires4_1_, request0_.addressLine1 as addressl5_1_, request0_.addressLine2 as addressl6_1_, request0_.agency as agency7_1_, request0_.city as city8_1_, request0_.email as email9_1_, request0_.firstName as firstna10_1_, request0_.lastName as lastnam11_1_, request0_.phone as phone12_1_, request0_.relationship as relatio13_1_, request0_.state as state14_1_, request0_.zipcode as zipcode15_1_, request0_.submitted as submitt16_1_ from Request request0_ where request0_.firstName like @P1]: $2could not execute query: java.util.concurrent.CompletionException: io.vertx.mssqlclient.MSSQLException: {number=102, state=1, severity=15, message='Incorrect syntax near '?'.', serverName='aa3ae4a0fd3c', lineNumber=1, additional=[io.vertx.mssqlclient.MSSQLException: {number=8180, state=1, severity=16, message='Statement(s) could not be prepared.', serverName='aa3ae4a0fd3c', lineNumber=1}]}
bug

全てのコメント13件

そのSQLには奇妙なことがあります。

top n代わりにoffset ... fetch ... top nを使用しているのはなぜですか。 そして、なぜ冗長な括弧ですか?

PanacheはクエリでsetMaxResults()を使用していると思います。

まあそれは確かにあるべきです。 Panacheには、独自のSQL生成を行ったり行ったりするビジネスはありませんよね、@ FroMage?

さて、私はこれをプレーンHRで試しましたが、次のようになります。

select hqlquerypa0_.id as id1_0_, hqlquerypa0_.description as descript2_0_, hqlquerypa0_.name as name3_0_, hqlquerypa0_.type as type4_0_ from Flour hqlquerypa0_ order by hqlquerypa0_.id offset <strong i="6">@P1</strong> rows fetch next <strong i="7">@P2</strong> rows only

ですから、これはパナッシュ関連の問題であるに違いないと私には思えます。

レビューをありがとうございました。スタック内のいくつかのプロジェクトに連絡します。 トレースログに示されている唯一のHQLだったのでFROM myproject.entities.Request WHERE requestor.firstName LIKE ?1 、私はのほか仮定top(?)のためのMS SQLの実装から来ていたsetMaxResults()あなたのポストに、しかし、SQLを完全に異なる構文を使用していることを示しています。

それでも問題が発生するので、次のHQLを使用するために、で注文を追加してみました: FROM myproject.entities.Request WHERE requestor.firstName LIKE ?1 ORDER BY submitted

2021-08-05 16:20:37,992 DEBUG [org.hib.hql.int.ast.QueryTranslatorImpl] (vert.x-eventloop-thread-19) HQL: FROM myproject.entities.Request WHERE requestor.firstName LIKE ?1 ORDER BY submitted
2021-08-05 16:20:37,992 DEBUG [org.hib.hql.int.ast.QueryTranslatorImpl] (vert.x-eventloop-thread-19) SQL: select request0_.id as id1_1_, request0_.caseId as caseid2_1_, request0_.caseNumber as casenumb3_1_, request0_.expires as expires4_1_, request0_.addressLine1 as addressl5_1_, request0_.addressLine2 as addressl6_1_, request0_.agency as agency7_1_, request0_.city as city8_1_, request0_.email as email9_1_, request0_.firstName as firstna10_1_, request0_.lastName as lastnam11_1_, request0_.phone as phone12_1_, request0_.relationship as relatio13_1_, request0_.state as state14_1_, request0_.zipcode as zipcode15_1_, request0_.submitted as submitt16_1_ from Request request0_ where request0_.firstName like ? order by request0_.submitted

これにより、次のSQLを実行しようとしました。

2021-08-05 16:20:38,022 DEBUG [org.hib.SQL] (vert.x-eventloop-thread-19)
    select
        request0_.id as id1_1_,
        request0_.caseId as caseid2_1_,
        request0_.caseNumber as casenumb3_1_,
        request0_.expires as expires4_1_,
        request0_.addressLine1 as addressl5_1_,
        request0_.addressLine2 as addressl6_1_,
        request0_.agency as agency7_1_,
        request0_.city as city8_1_,
        request0_.email as email9_1_,
        request0_.firstName as firstna10_1_,
        request0_.lastName as lastnam11_1_,
        request0_.phone as phone12_1_,
        request0_.relationship as relatio13_1_,
        request0_.state as state14_1_,
        request0_.zipcode as zipcode15_1_,
        request0_.submitted as submitt16_1_
    from
        Request request0_
    where
        request0_.firstName like <strong i="10">@P1</strong>
    order by
        request0_.submitted offset 0 rows fetch next ? rows only

したがって...同じ問題がまだ存在し、パラメーターの置換が適切に行われなかった(現在はfetch next ? rows only )が、生成されたSQL構文が例に一致するように変更された。

Quarkusにはまだhibernate-reactive-core1.0.0.CR9が含まれていないため、このバージョンとhibernate-core5.5.5.Finalのバージョンを具体的に上書きしました。 依存関係が欠落している可能性がありますか?

HibernateクエリがPanacheio.quarkus.hibernate.reactive.panache.common.runtime.CommonPanache QueryImpl:L254で作成されていると思われる場所を調べましたが、 setFirstResultsetMaxResultsのみを使用しているようです。クエリで。 デバッガーでクエリオブジェクトを確認し、そのcreateQueryメソッドの最後に、基になるReactiveQueryImplにfirstRow = 0とmaxRows = 25を含むqueryOptionsがあります。

助けに感謝します! (プレビューを使用していることを理解してください)

おそらくSQLServerParameters.processLimit()にバグが見つかったと思います

Panacheは、firstRow = 0で休止状態のクエリを作成しています。

org.hibernate.reactive.loader.ReactiveLoader.executeReactiveQueryStatementSQLServer2012LimitHandler.getOffsetFetch()が呼び出されます。

if ( !LimitHelper.hasFirstRow( selection ) ) {
    return " offset 0 rows fetch next ? rows only";
}
return " offset ? rows fetch next ? rows only";

したがって、この時点でのSQLはoffset 0 rows fetch next ? rows only終わります。 ?の代わりに0に注意してください。
SQLServerParameters.processLimit()

        if (isProcessingNotRequired(sql)) {
            return sql;
        }

        // Replace 'offset ? fetch next ? rows only' with the <strong i="17">@P</strong> style parameters for Sql Server
        int index = hasOffset ? parameterArray.length - 1 : parameterArray.length;
        int pos = sql.indexOf( " offset ?" );
        if ( pos > -1 ) {
            String sqlProcessed = sql.substring( 0, pos ) + " offset @P" + index++ + " rows";
            if ( sql.indexOf( " fetch next ?" ) > -1 ) {
                sqlProcessed += " fetch next @P" + index + " rows only ";
            }
            return sqlProcessed;
        }

        return sql;

sql.indexOf( " offset ?")が問題です。LimitHandlerはすでにオフセットを0にハードコーディングしているため、サブストリングoffset ?が見つからないため、それ以上のパラメーターの処理は試行されません。
fetch next ?探しているネストされた文字列の一致は、 offset一致の外に移動する必要がありますか?

@bharward HibernateReactiveのみを使用するテストケースを作成

Panacheを使用しているものも見ていくと思いますが、このリポジトリはそのような問題に適した場所ではありません

最初の結果ではなく、最大の結果のみを設定するテストが欠落しているのではないかと思います。

基本的なものがあります: https

@gavinking@ DavideD-ありがとう。 setFirstResult(0)setMaxResults(n) (nは任意の値> 0)の両方を実行する別のテストで、表示されているエラーが再現されるようです。

SQLServer2012LimitHandler.getOffsetFetch()は、firstResult == 0( "offset 0 rows ...")の場合とfirstResult> 0( "offset?rows")の場合で異なるSQLを作成します。

それでも役立つ場合は、数日で、HRのみの小さな例を作成して再現するか、HQLQueryParameterNamedLimitTestを変更して説明したようにテストを追加することができます。

ああ、あなたは正しいです、このテストはHQLQueryParameterNamedLimitTest失敗します:

    <strong i="7">@Test</strong>
    public void testFirstResultZeroAndMaxResults(TestContext context) {
        test(
                context,
                openSession()
                        .thenCompose( s ->
                                s.createQuery( "from Flour order by id" )
                                        .setFirstResult( 0 )
                                        .setMaxResults( 10 )
                                        .getResultList()
                                        .thenAccept( result -> {
                                            context.assertEquals( 3, result.size() );
                                        } )
                        )
        );
    }

あとで見てみます

@DavideDは、あなたが提案したテストに加えて、

       <strong i="7">@Test</strong>
    public void testFirstResultZeroAndMaxResultsWithoutOrderBy(TestContext context) {
        test(
                context,
                openSession()
                        .thenCompose( s ->
                                s.createQuery( "from Flour" )
                                        .setFirstResult( 0 )
                                        .setMaxResults( 10 )
                                        .getResultList()
                                        .thenAccept( result -> {
                                            context.assertEquals( 3, result.size() );
                                        } )
                        )
        );
    }

違いは、「注文者」を削除することです。 その理由は、ということですSQLServer2005LimitHandlerのようクエリを書き込み、 select top(?) ...クエリは、「順」が含まれていない時はいつでも、それはそれは使用たときにoffset ? fetch next ?構文を。 したがって、2つのテストケースが必要だと思います。

とても有難い!!

このページは役に立ちましたか?
0 / 5 - 0 評価