考慮下列實體:JPA批量刪除多列主鍵
@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個刪除請求。所以我寫了下面的代碼在吾道產生像刪除查詢DELETE FROM OBJECT_TABLE WHERE(ID1,ID2)IN((someId1,someId2),(someOtherId1,someOtherId2),...)
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數據庫上執行
EDIT - >解決USING @Guenther SOLUTION
問題是通過構建具有多個謂詞相同的請求來解決。
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和ID2 = someId2)OR(ID1 = someOtherId1和ID2 = someOtherId2),或)
如果我正確理解你的答案。我應該建立一個請求,如** DELETE FROM OBJECT_TABLE WHERE ID1 IN(?,?,?,...)和ID2 IN(?,?,?,...)**,這是不同的請求。 –
你說得對,那是不一樣的。我的錯。我會編輯答案。您需要爲每個值對添加'和'。 – Guenther