2016-04-30 209 views
1

所以,我有一个一对多的关系在我的entites之一:你可以在JPA实体中使用性能良好的lambda表达式吗?

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

我想包含一些标准,根据这些“成果”的内部对象:

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

一点也没有” t似乎是非常有效的,因为我猜所有的项目都会在任何过滤完成之前加载到内存中,尽管过滤和限制。

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

lambda可以与JPA一起使用吗?

+1

正如@Sleiman所说,这可能是一项非常昂贵的操作。为什么要用一个简单的线性搜索替换部分构建的数据库来处理子句?如果是由我来审查,我会拒绝此代码。 – stdunbar

回答

3

无论好坏取决于结果集的大小。但值得知道执行代码时会发生什么。

  1. 全扫描将执行对db表
  2. 整个表的数据将通过网络线行进
  3. 整个结果集将被加载到JVM主存储器
  4. 的线性扫描在当你做的过滤器过流

上面的代码将执行整个结果不是从旧的方式对环有什么不同。

2

JPA实体应该是普通类,集合,get/set方法等等的POJO类。我建议将所有逻辑移至DAO类。

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

0

使用Jinq,可以使用lambda表达式进行查询并获得良好的数据库性能,在Java中使用JPA也是如此。

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 

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

相关问题