【发布时间】:2015-08-03 17:45:18
【问题描述】:
当我们想在可空列上使用基于函数的索引时,Oracle 有一种常用方法来使用谓词 NVL(some_column, ' ') = ' ',如下所示:
CREATE INDEX idx_some_index ON some_table (NVL(some_column, ' '));
JPA 中内置的谓词:
criteriaBuilder.equal(criteriaBuilder.coalesce(root.get("some_column"), " "), " ")
hibernate实现(也可以通过eclipse实现)生成的结果SQL谓词:
nvl(sometable0_.some_column, ?)=?
由于使用了第一个绑定参数,它不允许 oracle 使用基于函数的索引。因此,oracle 使用了 FULL SCAN。
根据代码 (LiteralExpression.render(...)),JPA 实现为所有字符串文字(非数字文字)创建绑定参数。我认为它使用这种方法来避免可能的 SQL 注入...
数字列的类似情况可以正常工作:nvl(sometable0_.some_column, -1)=-1(第二个-1 可以替换为criteriaBuilder.parameter(...),以不强制Oracle 对每个新参数值进行硬解析)。
所以我的问题是:在我绝对确定不可能注入的情况下,是否有任何合法的方法可以强制 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);
}
//...
}
但我不认为这是正确的。
【问题讨论】:
标签: oracle hibernate jpa coalesce nvl