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

2022-09-01 03:23:53

我希望比我更具有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 Query对象,这些对象已传递到函数中。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%的时间。

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


答案 1

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

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

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


答案 2

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


推荐