7

状況
jTDS を使用して MSSQL 2008 データベースに接続する (Tomcat) Java Web アプリケーションがあります。この Java アプリケーションは、ユーザー入力を使用して MSSQL ストアド プロシージャの 99% を実行します。

問題
jTDS ドライバーは、(アプリケーション内のさまざまな場所で) ときどきエラーを返します。

ストアド プロシージャ、関数、トリガー、またはビューの最大ネスト レベルを超えました (制限 32)。

prepareSQL=0これは、jTDS 接続文字列に追加することで回避できます。その後、エラーはどこでも消えますが、 の他のすべての値でprepareSQLは、エラーは残ります。jTDS が追加するストアド プロシージャのネスト レベルの数はわかりませんが、明らかに、アプリケーションには多すぎます。

質問

  1. prepareSQL=3ストアド プロシージャのみを実行し、もちろん Java コードでプリペアド ステートメントを使用すると、 (またはprepareSQL=0)はどれくらいの効果があるでしょうか? 言い換えれば、すべてのWebサイトで「prepareSQL=0本番環境では使用しないでください」と言っているのを見つけましたが、それはこの状況にも当てはまりますか?

  2. 推奨される解決策でない場合prepareSQL=0や、セキュリティ上の問題などがある場合は、別のドライバーを探す必要があります。jTDS は過去 2 年間更新されておらず、Microsoft には JDBC 4.0 用のドライバーがあります。ただし、jTDS と Microsoft の JDBC 4.0 ドライバーのベンチマークや比較は見つかりません。Microsoft の 2.0 および 3.0 ドライバーでは、jTDS の方が高速で、優れており、効率的であるというのが一般的な意見のようです。JDBC 4.0 の場合もそうですか、それとも Microsoft はこれで競合他社を追い越しましたか?

4

1 に答える 1

2

prepareSQL が 0 でない場合、jTDS はネストにちょうど1レベルを追加します。次の手順を検討してください。

CREATE PROCEDURE F @v int
AS
BEGIN
    select @v = @v - 1
    IF @v = 0 SELECT @v
    ELSE EXEC F @v
END

そしてそれを使用するJavaコード:

 Connection connection = DriverManager.getConnection("jdbc:jtds:sqlserver://xxx.xxx.xxx.xxx:1433/xxx;prepareSQL=0");
 PreparedStatement statement = connection.prepareStatement("EXEC F ?");
 statement.setInt(1, 32);
 statement.execute();

prepareSQL を 0 以外の値に設定すると、「ストアド プロシージャ、関数、トリガー、またはビューの最大ネスト レベルを超えました (制限 32)」で失敗します。コードがネストを多用している理由を見つける必要がありますか? prepareSQL=0 により、mssql が stamements を使用するのを防ぎ、実行するたびに SQL を強制的に解析するようにします。ステートメントの実行時間がステートメントのコンパイル時間よりもはるかに長い場合、大きな問題にはなりません (たとえば、ストアド プロシージャが 10 秒実行される場合、コンパイルに 10 ミリ秒以上かかっても問題ありません)。同じ問題が発生するため、ドライバーを変更しても役に立ちません。

于 2013-02-27T06:37:39.617 に答える