对于包含IN
条件且绑定参数很多的查询,我们遇到了问题,因为它们具有多种变体,并且很快会使查询缓存溢出。
如果要为in子句指定30个以上的绑定值,我想检入sql语句的condition子句并引发异常。
我可以使用VisitListener
吗?
我可以使用org.jooq.VisitContext#clause查找in
或not in
条件,但是我不能在没有反射的情况下检查org.jooq.impl.InCondition#values
的大小。
现在我被迫做这样的事情:
public class MyVisitListener extends DefaultVisitListener {
@Override
public void visitStart(VisitContext context) {
if (context.clause() == Clause.CONDITION_IN || context.clause() == Clause.CONDITION_NOT_IN) {
try {
Field field = context.queryPart().getClass().getDeclaredField("values");
field.setAccessible(true);
Object value = field.get(context.queryPart());
if (((Object[]) value).length > 30) {
throw new IllegalArgumentException("More than 30 bind values specified!");
}
} catch (NoSuchFieldException | IllegalAccessException e) {
//throw new UnknownException("Can`t check size of field 'values' in " + context.queryPart().getClass().getName(), e);
}
}
}
}
是否有更方便的方法(jOOQ 3.10.8 pro)?
答案 0 :(得分:4)
另一个解决问题的方法通常是可以接受的,它是启用optional in-list padding in jOOQ:
<settings xmlns="http://www.jooq.org/xsd/jooq-runtime-3.10.8.xsd">
<inListPadding>true</inListPadding>
</settings>
这不完全是您想要的,但可能正是您需要的。简而言之,它使jOOQ生成{@ 1}}的条件,这些条件总是2的幂。这使得查询缓存更加容易。
代替此(8个查询):
IN
您将看到此信息(4个查询,并且随着长度的增加而变得越来越好):
-- Original
SELECT * FROM AUTHOR WHERE ID IN (?)
SELECT * FROM AUTHOR WHERE ID IN (?, ?)
SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?)
SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?)
SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?)
SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?, ?)
SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?, ?, ?)
SELECT * FROM AUTHOR WHERE ID IN (?, ?, ?, ?, ?, ?, ?, ?)
答案 1 :(得分:3)
我来这里是为了建议IN
列表填充(as Petr did very nicely, in his answer)。除此之外,正确的VisitListener
解决方案是侦听CONDITION_IN
子句,记住某种堆栈中的信息,然后计算紧随其后的所有FIELD
子句,直到CONDITION_IN
子句再次结束。并且请记住,FIELD
列表中可能还会有一个表达式(同样包含多个IN
子句),而不是绑定值。
很显然,彼得的建议容易得多。