如何使用JPA检索多个对象?

Coj*_*nes 7 java orm hibernate jpa jpa-2.0

我在这个数据模型中使用JPA2/hibernate:

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

我想检索StockGroup的包含Stock的位置visible==true.
我想出了这个错误的代码:

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();
Run Code Online (Sandbox Code Playgroud)

是否可以使用一个CriteriaQuery检索StockGroup和Stock对象,或者JPA是否只能一次填充一个类型?或者我可以在.getStocks()懒惰填充时添加一些标准吗?

Jes*_*rSM 10

这样做的诀窍是返回一个元组,其中包含Stock和StockGroup之间的老式连接,如下所示:

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();
Run Code Online (Sandbox Code Playgroud)

那么元组不是完全类型安全的,但你可以通过位置(或别名,如果你给你的选择表达式或根别名)来到达它:

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

    System.out.println("Stock is : " + s + "    .... StockGroup: " + sg);
}
Run Code Online (Sandbox Code Playgroud)

关于JPA2 Typesafe查询的IBM DeveloperWorks上有一篇很好的文章.

祝你的JPA2努力好运!