JPA批量删除多列主键

时间:2017-09-27 08:28:04

标签: java jpa bulk-delete

鉴于以下实体:

@Entity(name = "Object")
@Table(name = "OBJECT_TABLE")
public class ObjectEntity {
    @EmbeddedId
    private ObjectEntityPk id;

    @Column(name = "SOME_ATTIBUTE")
    private String someAttribute;

    ... Getters/Setters
}

以下主要关键对象:

@Embeddable
public class ObjectEntityPk {
    @Column(name = "id1")
    private String id1;

    @Column(name = "id2)
    private Long id2;

    ... Getters/Setters
}

我有50个ObjectEntity要删除,我想避免循环它并执行50个删除请求。所以我在我的dao中编写了以下代码来生成删除查询,如 DELETE FROM OBJECT_TABLE WHERE(id1,id2)IN((someId1,someId2),(someOtherId1,someOtherId2),...) < / p>

public void deleteObjects(final List<ObjectEntity> objects) {
    CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
    CriteriaDelete<ObjectEntity> deleteCriteria = criteriaBuilder.createCriteriaDelete(ObjectEntity.class);
    Root<ObjectEntity> rootObject= deleteCriteria.from(ObjectEntity.class);

    Expression<ObjectEntityPk> expression = rootObject.get("id");
    Predicate predicate = expression.in(objects.stream().map(ObjectEntity::getId).collect(Collectors.toList()));
    deleteCriteria.where(predicate);
    this.entityManager.createQuery(deleteCriteria).executeUpdate();
}

除了生成的查询有问题。表单是正确的,但它没有正确绑定列名称。查看我得到的查询。

 DELETE FROM OBJECT_TABLE WHERE ((?, ?) IN ((?, ?), (?, ?), (?, ?), (?, ?), ...)) 
 bind => [null, null, 0d287cacc63ff01b5222bf0bb2b2c794, 8105793672, 222a1399065f41b10814d88690c32bcf, 8105793874, 0b0c2f8e73475759872eb97a96f942a3, 8105794177, ...]

我不明白为什么我的列名没有绑定。我是否错过了Entity或Pk的内容?

提前感谢。

PS:生成的查询在Oracle数据库上执行

编辑 - &gt;使用@Guenther解决方案解决

通过使用多个谓词构造相同的请求来解决问题。

public void deleteObjects(final List<ObjectsEntity> objects) {
    CriteriaDelete<ObjectEntity> deleteCriteria = this.entityManager.getCriteriaBuilder()
                    .createCriteriaDelete(ObjectEntity.class);

    Root<ObjectEntity> rootObject = deleteCriteria.from(ObjectEntity.class);

    List<Predicate> predicates = objects.stream().map(n -> generateAndPredicate(n, rootObject))
                    .collect(Collectors.toList());

    Predicate predicate = this.entityManager.getCriteriaBuilder().or(predicates.toArray(new Predicate[predicates.size()]));

    deleteCriteria.where(predicate);

    this.entityManager.createQuery(deleteCriteria).executeUpdate();
}

private Predicate generateAndPredicate(final ObjectEntity object,
    final Root<ObjectEntity> rootObject) {
    Predicate id1Equal = this.entityManager.getCriteriaBuilder().equal(rootObject.get("id").get("id1"),
                    object.getId().getId1());
    Predicate id2Equal = this.entityManager.getCriteriaBuilder().equal(rootObject.get("id").get("id2"),
                    object.getId().getId2());
    return this.entityManager.getCriteriaBuilder().and(id1Equal, id2Equal);
} 

最终请求看起来像 DELETE FROM OBJECT_TABLE WHERE((ID1 = someId1 AND ID2 = someId2)OR(ID1 = someOtherId1 AND ID2 = someOtherId2)OR ...)

1 个答案:

答案 0 :(得分:0)

生成的SQL错误。无法绑定列名称。这是因为JPA不支持in语句的多个列。更多细节可以在JPA query for select which multiple values in the "IN" clause

找到

您需要一起创建func addObject(){ var arrayName:[String] = ["Name1", "Name2", "Name3"] arrayName.insert("Name0", at: 0) print("---> ",arrayName) } Output: ---> ["Name0","Name1", "Name2", "Name3"] 个谓词和id.id1 = x and id.id2 = y个列表。

作为替代方案,您可以使用本机查询,如上面引用的答案中所述。