你能在JPA实体中使用具有良好性能的lambda表达式吗?

时间:2016-04-30 22:32:17

标签: java jpa lambda

所以,我在其中一个网站中有一个OneToMany关系:

@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH }, fetch = FetchType.LAZY)
@OrderBy("priority")
    private List<Result> results

我希望得到包含在这些&#34;结果中的对象&#34;基于某些标准:

Stream<Item> itemsToReturn = results.stream().filter(result -> result.getPriority() > 5)
                .map(Result::getItem)
                .filter(/*some filtering logic*/)
                .limit(numberOfItems);

它似乎并不是非常有效,因为我猜所有的项目都会在过滤完成之前加载到内存中,尽管有过滤和限制。

我的假设是否正确?如果是这样,我可以做一些事情,以便我可以在这个实体中使用lambda,或者我应该编写一个JPA查询来获取这些项目吗?

lambda可以和JPA一起使用吗?

3 个答案:

答案 0 :(得分:3)

是否好是取决于你的结果集有多大。但是值得知道在执行代码时会发生什么。

  1. 将在db表
  2. 上执行完整扫描
  3. 整个表格数据将通过网络线传输
  4. 整个结果集将加载到JVM主存储器
  5. 当您通过流
  6. 执行文件管理器时,线性扫描将在整个结果上执行

    以上代码与旧式for-loop没有任何不同。

答案 1 :(得分:2)

JPA实体应该是具有普通字段,集合,get / set方法的POJO类,仅此而已。我建议将所有逻辑移到DAO类。

回答你的问题:JPA已经过滤了(又名Criteria API),其运行速度足够快。在大多数情况下,不需要使用lambdas进行过滤。

答案 2 :(得分:0)

使用Jinq,可以在使用JPA的Java中使用lambdas进行查询并获得良好的数据库性能。

Jinq与C#中的Linq类似,因此lambda查询被转换为SQL(JPQL)并由数据库执行,就像任何其他查询一样 - 它们不是由Java执行的。 (*)

一个与你的略有相似的简单示例在Jinq中看起来像这样:

List<Item> items = jinq.users()
    .where(user -> user.getId() == someId)
    .selectAllList(user -> user.getItems())        // <- a very simple type of join
    .where(item -> item.getPriority() > 5)
    .where(item -> /*some more filtering logic*/) 
    .limit(numberOfItems)
    .toList();                                     // <- this fetches the result from the DB

(*)注意,这显然也意味着你可以在lambdas中放置什么限制 - 你不能调用任意的java方法,例如,因为数据库引擎无法执行那些。只允许一组有限的方法 - 实体关系getter-methods是这种允许方法的一个例子。