2011-01-11 28 views
5

Tôi đang sử dụng JPA2/hibernate với mô hình dữ liệu này:Làm cách nào tôi có thể truy xuất nhiều đối tượng bằng JPA?

class Stock { 
    @ManyToOne 
    private StockGroup stockGroup; 
    private boolean visible; 
} 
class StockGroup { 
    @OneToMany(mappedBy = "stockGroup") 
    private List<Stock> stocks; 
} 

Tôi muốn lấy StockGroup của chứa Cổ, nơi visible==true.
tôi đã đi lên với mã lỗi này:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<StockGroup> q = cb.createQuery(StockGroup.class); 
Root<StockGroup> r = q.from(StockGroup.class); 
Join<StockGroup, Stock> j = r.join(StockGroup_.stocks, JoinType.INNER); 
Predicate p = cb.equal(j.get(Stock_.visible), true); 

// This becomes a cartesian product :(
List<StockGroup> l = em.createQuery(q.where(p)).getResultList(); 
// Stocks are not filtered on visible :(
l.get(0).getStocks(); 

Có thể lấy đối tượng StockGroup và cổ với một CriteriaQuery hoặc có thể JPA chỉ điền một loại cùng một lúc? Hoặc tôi có thể thêm một số Tiêu chí khi .getStocks() được lấp đầy không?

Trả lời

8

Bí quyết để làm điều này đang trở lại một tuple chứa một lỗi thời tham gia giữa chứng khoán và StockGroup, như thế này:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Tuple> q = cb.createQuery(Tuple.class); 
Root<Stock> sRoot = q.from(Stock.class); 
Root<StockGroup> sgRoot = q.from(StockGroup.class); 

q.select(cb.tuple(sRoot, sgRoot)).where(
    cb.and(cb.equal(sRoot.get(Stock_.stockGroup), sgRoot), 
     cb.isTrue(sRoot.get(Stock_.visible)))); 
List<Tuple> l = em.createQuery(q).getResultList(); 

Các tuple là sau đó không hoàn toàn là loại an toàn, nhưng bạn có thể đạt được nó bởi vị trí (hoặc bằng bí danh, nếu bạn đã đưa ra chọn biểu hoặc rễ của bạn một bí danh):

for (Tuple t : l) { 
    Stock s = (Stock) t.get(0); 
    StockGroup sg = (StockGroup) t.get(1); 

    System.out.println("Stock is : " + s + " .... StockGroup: " + sg); 
} 

có một good article on IBM DeveloperWorks on JPA2 Typesafe Queries.

Chúc bạn may mắn trong nỗ lực JPA2 của mình!

+0

Nếu sợ điều này ... kết nối thủ công, phôi không an toàn, cú pháp vebose và đặt đối tượng theo cách thủ công. Có lẽ tôi cần phải chuyển sang một cái gì đó như OpenJPA hoặc Querydsl. Tuy nhiên, bạn vẫn trả lời câu hỏi của tôi một cách hoàn hảo (tôi đã đọc bài viết enitre). Điểm thưởng cho bạn nếu bạn trả lời phần thứ hai: Nếu tôi mới chỉ truy xuất StockGroups, tôi có thể thêm một số Tiêu chí khi .getStocks() được gọi không? Nói cách khác, tôi có thể gây rối với đối tượng proxy không? – Cojones

+0

Tôi không nghĩ rằng nó được hỗ trợ trong JPA - Trường hợp không có cấu trúc như vậy (bộ sưu tập được lọc), vì bạn sẽ nhận được một bộ sưu tập không đầy đủ trong đối tượng của bạn. Tôi cũng không hiểu OpenJPA sẽ giúp bạn như thế nào, và tôi không biết đủ về QueryDsl để đưa ra lời khuyên. Lấy làm tiếc! – JesperSM

+0

Tuy nhiên, bạn có thể thêm một số phương pháp/người trợ giúp cấp cao hơn để thực hiện việc tham gia thủ công, chẳng hạn như manualJoin (cb, sgRoot, sRoot, Stock_.group, cb.isTrue (sRoot.get (Stock_.visible))) và có lẽ bọc danh sách tuple cho phù hợp, như một ban nhạc hỗ trợ các loại? Thật đáng tiếc là họ đã không làm cho Tuple1 , Tuple2 , v.v. – JesperSM

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