NVL(some_column, ' ') = ' '
次のように、null 許容列で関数ベースのインデックスを使用する場合、Oracle には述語を使用する一般的な方法があります。
CREATE INDEX idx_some_index ON some_table (NVL(some_column, ' '));
JPAで構築された述語:
criteriaBuilder.equal(criteriaBuilder.coalesce(root.get("some_column"), " "), " ")
休止状態の実装によって生成された結果の SQL 述語 (Eclipse の実装によっても):
nvl(sometable0_.some_column, ?)=?
最初のバインド パラメータを使用するため、オラクルは関数ベースのインデックスを使用できません。その結果、Oracle は FULL SCAN を使用します。
コード ( ) によると、LiteralExpression.render(...)
JPA 実装は、すべての文字列リテラル (非数値リテラル) のバインド パラメーターを作成します。このアプローチを使用して、SQLインジェクションの可能性を回避していると思います...
数値列の同様のケースは正常に機能します: nvl(sometable0_.some_column, -1)=-1
(2番目は、新しいパラメータ値ごとにOracleにハード解析を強制しない-1
ように置き換えることができます)。criteriaBuilder.parameter(...)
だから私の質問:インジェクションが不可能であると確信している場合に、JPAにバインドパラメータを使用させないようにする法的方法はありますか?
ps。次のように、式の独自の実装 (基準ビルダーをバイパスして構築) を使用できます。
public class UnsafeLiteralExpression<T> extends ExpressionImpl<T> implements Serializable {
@SuppressWarnings({ "unchecked" })
public UnsafeLiteralExpression(T literal) {
this((Class<T>) determineClass( literal ), literal );
}
public UnsafeLiteralExpression(Class<T> type, T literal) {
super(null, type );
this.literal = literal;
}
//...
public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
return renderProjection(renderingContext);
}
//...
}
しかし、私はこれが正しいとは考えていません。