2009-07-02 36 views
6

Tôi có một đối tượng JPA trong đó có một mối quan hệ nhiều-nhiều như thế này:Làm cách nào để sử dụng JPQL để xóa các mục nhập khỏi bảng tham gia?

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

Có không phải là một đối tượng JPA cho RolePrivilege, vì vậy tôi không chắc chắn làm thế nào để viết một truy vấn JPQL xóa các mục từ trường privs của một đối tượng role. Ví dụ, tôi đã thử điều này, nhưng nó không hoạt động. Nó phàn nàn rằng Role.privs không được ánh xạ.

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

Tôi không chắc nên thử làm gì khác. Tôi có thể tất nhiên chỉ cần viết một truy vấn bản địa mà xóa từ bảng tham gia RolePrivilege. Tuy nhiên, tôi lo lắng rằng làm như vậy sẽ tương tác xấu với các đối tượng được lưu trong bộ nhớ cache cục bộ mà sẽ không được cập nhật bởi truy vấn gốc.

Thậm chí có thể viết JPQL để xóa mục nhập khỏi bảng tham gia như thế này không? Nếu không, tôi có thể tải tất cả các đối tượng Role và xóa các mục từ bộ sưu tập privs của từng đối tượng và sau đó tiếp tục tồn tại từng vai trò. Nhưng có vẻ ngớ ngẩn để làm điều đó nếu một truy vấn JPQL đơn giản sẽ làm tất cả cùng một lúc.

Trả lời

3

Tuyên bố cập nhật và xóa JPQL cần tham chiếu đến tên Thực thể, không phải tên bảng, vì vậy tôi nghĩ bạn không hài lòng với cách tiếp cận bạn đã đề xuất. Tùy thuộc vào nhà cung cấp JPA của bạn, bạn có thể xóa các mục từ JoinTable bằng cách sử dụng câu lệnh SQL thô đơn giản (nên 100% di động) và sau đó tương tác với API của nhà cung cấp bộ nhớ cache của bạn để loại bỏ dữ liệu. Ví dụ trong Hibernate bạn có thể gọi đuổi() hết hạn tất cả "Role.privs" bộ sưu tập từ bộ nhớ cache cấp 2:

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

Đáng tiếc là tôi không làm việc với các API JPA đủ để biết chắc chắn những gì chính xác là được hỗ trợ.

2

Java là ngôn ngữ hướng đối tượng và toàn bộ điểm ORM là ẩn chi tiết của các bảng tham gia và như vậy từ bạn. Do đó, ngay cả việc dự tính xóa từ một bảng tham gia mà không xem xét hậu quả sẽ là lạ.

Không, bạn không thể làm điều đó với JPQL, đó là dành cho các thực thể.

Truy lục các thực thể ở một trong hai đầu và xóa bộ sưu tập của chúng. Điều này sẽ loại bỏ các mục nhập bảng. Hướng đối tượng.

2

Tôi cũng đang tìm cách tiếp cận JPQL để xóa mối quan hệ nhiều-nhiều (có trong bảng tham gia). Rõ ràng, không có khái niệm về các bảng trong ORM, vì vậy chúng tôi không thể sử dụng các hoạt động DELETE ... Nhưng tôi muốn có một toán tử đặc biệt cho các trường hợp này. Một cái gì đó như LINK và UNLINK. Có lẽ một tính năng trong tương lai?

Dù sao, những gì tôi đã làm để đạt được nhu cầu này đã được làm việc với các bộ sưu tập được thực hiện trong các thực thể đậu, những người mà bản đồ quan hệ nhiều-nhiều.

Ví dụ, nếu tôi có một sinh viên lớp trong đó có một mối quan hệ nhiều-nhiều với Courses:

@ManyToMany 
private Collection <Courses> collCourses; 

tôi xây dựng trong thực thể một getter và setter cho bộ sưu tập đó. Sau đó, ví dụ từ một EJB, tôi lấy bộ sưu tập bằng cách sử dụng getter, thêm hoặc loại bỏ các khóa học mong muốn, và cuối cùng, sử dụng setter để gán bộ sưu tập mới. Và nó đã xong. Nó hoạt động hoàn hảo.

Tuy nhiên, lo lắng chính của tôi là hiệu suất.Một ORM là nghĩa vụ phải giữ một bộ nhớ cache lớn của tất cả các đối tượng (nếu tôi không nhầm), nhưng thậm chí sử dụng nó để làm việc nhanh hơn, tôi tự hỏi nếu lấy tất cả và mọi yếu tố từ một bộ sưu tập là thực sự hiệu quả ...

Bởi vì đối với tôi, nó không hiệu quả như truy xuất các đăng ký từ một bảng và sau đó lọc chúng bằng cách sử dụng Java thuần túy thay vì một ngôn ngữ truy vấn hoạt động trực tiếp hoặc gián tiếp với công cụ DB bên trong (SQL, JPQL ...).

Các vấn đề liên quan