Ebean - 动态查询 - 准备语句的不匹配参数计数错误

Posted

技术标签:

【中文标题】Ebean - 动态查询 - 准备语句的不匹配参数计数错误【英文标题】:Ebean - Dynamic Query - Prepared Statement's Mismatched Parameter Count Error 【发布时间】:2013-12-28 09:22:02 【问题描述】:

我希望比我更具有 Ebean 专业知识的人可以帮助我解决我现在正在排除的不稳定问题。

环境:

Java 1.7.0_17 mysql 5.5 Play Framework 2.1.1(不过我已经升级到 Play 2.2.1,这个问题依然存在)

我的主要问题是,当我重新启动 Play 时,我得到了交替的 SQLExceptions,所有这些都与 Ebean 正在创建的准备好的语句中的参数过多或过少有关。数据集 B 失败时,数据集 A 工作了一半,但重启 Play 时,数据集 B 工作,而数据集 A 失败。

我正在根据我编写并传递给函数的一组过滤器对象动态构建一个 Ebean 查询对象。 Ebean 查询正在查找满足每个过滤器给定要求的所有对象。

功能类似:

private List<Contact> contacts getContacts(Set<Filter> filters) 
    Query<Contact> query = Contact.find;
    for (Filter filter : filters) 
        filter.apply(query);
    
    List<Contact> contacts = query.findList();

过滤器示例:

public void apply(Query<Contact> query) 
    query.where().in("tags", getTags());

首先,Ebean 是否支持这种类型的查询构建?我相信它在大多数情况下都有效,但是,我在使用某些数据运行“getContacts”函数数百次时遇到问题,但只是有时......

所以坚持我,因为这个问题非常令人困惑。我还将详细介绍数据实际是什么的大部分细节,但如果您想要/需要更多信息,请询问。

数据集A的查询及异常:

select distinct t0.contact_id c0, t0.contact_uuid c1, t0.bounce c2 
from contact t0
join email_record u1 on u1.contact_id = t0.contact_id 
join contact_tag u2z_ on u2z_.contact_id = t0.contact_id 
join tag u2 on u2.tag_id = u2z_.tag_id  
where u1.status = ?  and t0.unit_id = ?  and u2.tag_id in (?,?,?)  and t0.unit_id in (? )  and t0.campaign_id in (?,?,?,?,?,?,?,?,?,?,?,?)

[PersistenceException: Error with property[19] dt[4]data[1464][java.lang.Integer]]
Caused by: java.sql.SQLException: Parameter index out of range (19 > number of parameters, which is 18).

然后Play重启后,数据集B的查询和异常:

[PersistenceException: Query threw SQLException:No value specified for parameter 19 Bind values:[SENT, 1290, 8988, 13032, 13052, 1290, 96, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 222] Query was: select distinct t0.contact_id c0, t0.contact_uuid c1, t0.bounce c2 from contact t0 join email_record u1 on u1.contact_id = t0.contact_id join contact_tag u2z_ on u2z_.contact_id = t0.contact_id join tag u2 on u2.tag_id = u2z_.tag_id where u1.status = ? and t0.unit_id = ? and u2.tag_id in (?,?) and t0.unit_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) and t0.campaign_id in (?,?,?,?,?,?,?,?,?,?,?,?) ]

我觉得这方面最令人困惑的部分是它如何切换,可靠地 100% 的时间在重启时来回切换。

以前有人见过这样的事情吗?只是为了增加混乱,它还在我们的生产环境中做了一些非常相似的事情(在不同的数据集上),但是即使在转储数据库并在本地加载它之后,我也无法在我的开发或测试机器上重现这一点。上面描述的问题在任何地方都可以重现。

【问题讨论】:

看起来这是我们正在处理的 Ebean 中的一个错误:github.com/ebean-orm/avaje-ebeanorm/issues/60 我始终无法解决它,并在 Rob 向 Ebean 项目提交修复程序之前解决了这个问题。 【参考方案1】:

我已经看到了类似的东西(在 DB2 上)使用准备好的语句。查询仅适用于执行的第一条语句具有的参数数量。只有它第一次被调用时具有的参数数量或更少才会起作用。它可能为参数预留了一个缓冲区 - 我相信它的行为就像额外的参数不存在一样。

如果第一次调用有足够的参数,那么一切都会好起来的,直到你点击超过那个数量的参数。但如果第一个查询只有 1 个参数,而下一次调用有多个参数,则下一次运行可能会立即失败。

检查它是否适用于常规语句而不是准备好的语句。如果是这样,则怀疑在处理可变数量参数的准备语句中存在错误。

【讨论】:

【参考方案2】:

Tags() 数组列表中有一个空值。如果您调试代码,您可以看到标记数组中有一个空值。

【讨论】:

即使 getTags() 函数的结果中有一个空值,我假设你指的是它,它也不会导致这种情况。

以上是关于Ebean - 动态查询 - 准备语句的不匹配参数计数错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 中将动态 SQL 查询转换为准备好的语句

如何使用准备好的语句动态绑定参数?

带有 sql 转义的动态 mysql 查询是不是与准备好的语句一样安全?

准备好的语句中的动态 where 条件的 SQL 注入

mysqli_stmt_bind_param():变量的数量与绑定参数中准备好的语句中的参数数量不匹配

Play Framework - Ebean - 没有为类“类名”注册 ScalarType