Linda撰写了关于新类型安全查询API的文章。我之前在这篇文章这篇文章中介绍了这个API背后的原因。

Linda没有提到的一个开放问题是查询执行。我正在努力说服其他成员,我们应该将类型安全贯穿到查询结果集中。以下是我几周前发给团队的一封信:

各位,我想出了一个重构方案,它为我们提供了一种实现类型安全结果集的方法,避免使用Result。在这个新的方法中,CriteriaQueryQuery都将有一个类型参数。如果你有一个单选,你可以编写如下代码:
  CriteriaQuery<Order> q = qb.create(Order.class);
  Root<Order> order = q.from(Order.class);
  q.select(order);

  Query<Order> eq = em.createQuery(q);
  List<Order> res= eq.getTypedResultList();
如果你有多个选择并且需要将它们封装在一个对象中,可以这样写:
  CriteriaQuery<OrderProduct> q = qb.create(OrderProduct.class);
  Root<Order> order = q.from(Order.class);
  Join<Item, Product> product = order.join(Order_.items)
                                     .join(Item_.product);
  q.select( qb.construct(OrderProduct.class, order, product) );

  Query<OrderProduct> eq = em.createQuery(q);
  List<OrderProduct> res= eq.getTypedResultList();
或者,如果你没有像OrderProduct这样的良好封装类,你可以退回到使用Result
  CriteriaQuery<Result> q = qb.create();
  Root<Order> order = q.from(Order.class);
  Join<Item, Product> product = order.join(Order_.items)
                                     .join(Item_.product);
  q.select( qb.result(order, product) );

  Query<Result> eq = em.createQuery(q);
  List<Result> res= eq.getTypedResultList();
这个更改使人们可以直接获取类型安全的实体列表或封装器,这是很多人要求的功能!

这个API的一个重大特点是,我无法编写一个选择Foo并将其放入List<Bar>中的查询。它真正实现了端到端的类型安全。

这个问题的关键是javax.persistence.Query目前没有所需的类型参数,并且有成百万的查询是根据JPA 1.0 API编写的,如果我们添加了类型参数,这些查询会突然出现编译器警告。因此,我们可能需要引入一个新的接口,比如TypesafeQuery或者类似的东西。


返回顶部