2009-07-02 3 views
6

이 같은 다 대다 관계가있는 JPA 오브젝트 있습니다JPQL을 사용하여 조인 테이블에서 항목을 삭제하는 방법은 무엇입니까?

@Entity 
public class Role { 
    //... 

    @ManyToMany(fetch=FetchType.EAGER) 
    @JoinTable(
    name="RolePrivilege", 
    joinColumns= 
     @JoinColumn(name="role", referencedColumnName="ID"), 
    inverseJoinColumns= 
     @JoinColumn(name="privilege", referencedColumnName="ID") 
    ) 
    private Set<Privilege> privs; 
} 

이 RolePrivilege에 대한 JPA의 객체가되지 않습니다, 그래서 삭제할 JPQL 쿼리를 작성하는 방법을 잘 모르겠어요 역할 객체의 privs 필드에있는 항목. 예를 들어,이 시도했지만 작동하지 않습니다. Role.privs가 매핑되지 않는다고 불평합니다.

DELETE FROM Role.privs p WHERE p.id=:privId 

다른 어떤 시도를해야할지 모르겠습니다. 물론 Join table RolePrivilege에서 삭제하는 네이티브 질의를 작성할 수 있습니다. 하지만 그렇게하면 네이티브 쿼리에 의해 업데이트되지 않는 로컬 캐시 된 개체와 심하게 상호 작용할 것이라고 걱정됩니다.

이렇게 조인 테이블에서 항목을 제거하는 JPQL을 작성할 수 있습니까? 그렇지 않은 경우 모든 Role 개체를로드하고 각 Role 개체를 privs 컬렉션에서 제거한 다음 각 역할을 지속 할 수 있습니다. 그러나 단순한 JPQL 쿼리가 모든 것을 한꺼번에 처리한다면 그것은 어리석은 것처럼 보입니다.

답변

3

JPQL update 및 delete 문은 테이블 이름이 아닌 엔티티 이름을 참조해야하므로 사용자가 제안한 접근 방식에서 벗어났습니다.

JPA 공급자에 따라 간단한 원시 SQL 문 (100 % 이식 가능해야 함)을 사용하여 JoinTable에서 항목을 삭제 한 다음 캐시 공급자 API와 프로그래밍 방식으로 상호 작용하여 데이터를 제거 할 수 있습니다. 충분히 정확히 무엇인지 확실히 알고

sessionFactory.evictCollection("Role.privs", roleId); //evict a particular collection of privs 
sessionFactory.evictCollection("Role.privs"); //evict all privs collections 

불행하게도 나는 JPA API를 사용하여 작동하지 않습니다 : Hibernate에서 예를 들어 당신은 2 레벨 캐시에서 모든 "Role.privs"컬렉션을 만료 EVICT()를 호출 할 수 있습니다 지원.

2

Java는 객체 지향 언어이며 ORM의 핵심은 조인 테이블 등의 세부 정보를 숨기는 것입니다. 따라서 결과를 고려하지 않고 조인 테이블에서 삭제를 고려하는 것조차 이상합니다.

아니요 엔티티의 경우 JPQL로 처리 할 수 ​​없습니다.

양쪽 끝에있는 엔티티를 검색하고 컬렉션을 지 웁니다. 그러면 조인 테이블 항목이 제거됩니다. 객체 지향.

2

또한 (결합 테이블에 포함 된) 다 대다 관계를 삭제하는 JPQL 방식을 찾고있었습니다. 분명히 ORM에는 테이블 개념이 없으므로 DELETE 연산을 사용할 수 없습니다 ... 그러나이 경우에는 특별한 연산자가 필요합니다. LINK 및 UNLINK와 같은 것입니다. 어쩌면 미래의 기능일까요?

어쨌든이 필요를 달성하기 위해 내가 해왔 던 것은 엔티티 bean에 구현 된 콜렉션, 즉 다 대다 관계를 맵핑하는 콜렉션에 대한 작업이었습니다. 예를 들어

, 나는 과정과 다 대다 관계가있는 클래스 학생 가지고있는 경우 :

@ManyToMany 
private Collection <Courses> collCourses; 

내가 엔티티에 해당 모음에 대한 getter와 setter를 구축합니다. 그런 다음 예를 들어 EJB를 사용하여 getter를 사용하여 컬렉션을 검색하고 원하는 Course를 추가 또는 제거한 다음 마지막으로 setter를 사용하여 새 컬렉션을 할당합니다. 그리고 끝났어. 그것은 완벽하게 작동합니다.

그러나 내 주된 걱정은 성능입니다.ORM은 모든 객체의 거대한 캐시를 유지하기로되어 있지만 (실수하지 않은 경우), 더 빠르게 작업하기 위해 사용하더라도 컬렉션의 모든 요소를 ​​모두 가져 오는 것이 실제로 효과적인지 궁금합니다.

왜냐하면 내게는 테이블에서 레지스트리를 검색하는 것만큼이나 비효율적이며 내부 DB 엔진 (SQL, JPQL ...)을 사용하여 직접 또는 간접적으로 작동하는 쿼리 언어 대신 순수 Java를 사후 필터로 사용하기 때문입니다.

관련 문제