2017-09-27 5 views
0

다음 엔티티 감안할 때 : 나는 삭제 50 ObjectEntity을하고 난 루프를 피하려고JPA의 대부분은 멀티 열이 삭제 기본 키

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

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

    ... Getters/Setters 
} 

:

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

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

    ... Getters/Setters 
} 

그리고 다음과 같은 기본 키 객체를 그것에 50 삭제 요청을 실행합니다. 그래서 같은 삭제 쿼리는 IN OBJECT_TABLE (ID1, ID2)에서 삭제를 생성하기 위해 내 DAO에 다음 코드를 작성 ((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, ...] 

내 열 이름이 바인딩되지 않은 이유를 모르겠다. 엔티티 또는 Pk에서 뭔가를 놓쳤습니까?

감사합니다.

PS : 생성 된 쿼리는 오라클 데이터베이스

수정을 실행한다 -> 여러 조건과 같은 요청을 구성함으로써 해결된다 @Guenther SOLUTION

문제 USING 해결.

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); 
} 

같은 최종 요청 모습 OBJECT_TABLE WHERE ((ID1 = someId1 AND ID2 = someId2) OR (ID1 = someOtherId1 AND ID2 = someOtherId2) OR ...)

답변

0

생성 SQL에서 삭제 잘못된 것입니다. 열 이름을 바인드 할 수는 없습니다. 이는 JPA가 in 문에 대해 여러 열을 지원하지 않는다는 사실 때문입니다. 자세한 내용은 당신이 함께 id.id1 = x and id.id2 = y 조건 및 or을의 목록을 만들 필요가 여기 JPA query for select which multiple values in the "IN" clause

찾을 수 있습니다.

위의 답변에서 언급 한 것처럼 기본 쿼리를 사용할 수도 있습니다.

+0

정확하게 대답을 이해했다면. 나는 같은 요청을하지 말아야 ** ** OBJECT_TABLE로부터 DELETE FROM ID1 (?,?,?, ...)과 ID2 IN (?,?,?, ...) ** 같은 요청을 만들어야한다. –

+0

당신이 맞습니다. 그것은 동일하지 않습니다. 내 실수. 나는 대답을 편집 할 것이다. 각 값 쌍에'and'를 추가해야합니다. – Guenther