对于具有多列 ID 的实体,我们需要将数据库中尚未存在的所有对象持久保存在给定列表中。由于要检查的对象数量很大,并且存储中的对象数量可能非常大,因此想法是使用它们的多列私钥和“WHERE ... IN (. ..)" 使用条件 API 构造的类型语句,以便它们可以在持久化之前从列表中删除。
这是尝试执行此操作的代码:
public void persistUnique(List<CdrEntity> cdrs) {
// find all the CDRs in the collection that are already in the DB
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<CdrEntity> query = criteriaBuilder.createQuery(CdrEntity.class);
Root<CdrEntity> cdrRoot = query.from(CdrEntity.class);
query.select(cdrRoot).where(cdrRoot.in(cdrs));
List<CdrEntity> nonUnique = entityManager.createQuery(query).getResultList();
// remove nonUnique elements from crds and persist
...
}
但是,至少使用 EclipseLink 2.4.1,这是实际发送到数据库的内容(为了便于阅读,省略了一些输出):
[EL Fine]: sql:...--SELECT SUBINDEX, ... FROM CDRS WHERE ((?, ?, ?, ?) IN ((?, ?, ?, ?), (?, ?, ?, ?), ...))
bind => [null, null, null, null, 2, 1362400759, 19415, 176, ...]
本质上,在主键列的适当列名应该在的地方,添加了许多参数,然后绑定(值为 null)。除此之外,查询很好,如果前四个 ?s 被实际的列名替换,则执行所需的结果。
然而,直接调用.in(...)
aRoot
似乎没有预期的结果。如果无法直接使用实体,我希望有某种Expression
可以代表多个列的列,然后这些列可能是调用的接收者.in(...)
,但我找不到任何列。
所以,问题是:如何正确地做到这一点?或者 JPA 根本不可能?或者只是 EclipseLink 中存在一个错误?