在使用DB时,为什么您更喜欢Java8流API而不是直接的hibernate/sql查询
最近,我在少数几个项目中看到了大量使用流过滤对象的代码,如:在使用DB时,为什么您更喜欢Java8流API而不是直接的hibernate/sql查询,java,hibernate,java-8,java-stream,Java,Hibernate,Java 8,Java Stream,最近,我在少数几个项目中看到了大量使用流过滤对象的代码,如: library.stream() .map(book -> book.getAuthor()) .filter(author -> author.getAge() >= 50) .map(Author::getSurname) .map(String::toUpperCase) .distinct()
library.stream()
.map(book -> book.getAuthor())
.filter(author -> author.getAge() >= 50)
.map(Author::getSurname)
.map(String::toUpperCase)
.distinct()
.limit(15)
.collect(toList()));
使用它而不是直接向数据库查询HQL/SQL,返回已经过滤过的结果,有什么好处吗
第二种方法不是更快吗?乍一看:流可以并行运行只需将代码更改为使用
parallelStream()
。(免责声明:如果仅仅更改流类型将产生正确的结果,当然这取决于特定的上下文;但是,是的,这可能很容易)
然后:流“invite”使用lambda表达式。而这些反过来又导致字节码指令的使用;与编写此类代码的“老派”类型相比,有时会获得性能优势。(为了澄清误解:invoke_dynamic是lambdas的属性,而不是streams!)
这些都是如今人们更喜欢“流”解决方案的原因(从一般的角度来看)
除此之外:这真的取决于。。。让我们看看您的示例输入。这看起来像是处理普通的Java POJO,它们已经驻留在内存中,在某种集合中。直接在内存中处理这样的对象肯定比在非进程数据库中工作要快
但是,当然:当上面的调用,比如
book.getAuthor()
将进行“深入”并实际与底层数据库对话时;那么,“在一个查询中完成全部工作”可能会提高性能 如果数据最初来自数据库,则最好在数据库中进行过滤,而不是获取所有内容并在本地进行过滤
首先,数据库管理系统擅长过滤,这是它们主要工作的一部分,因此它们针对过滤进行了优化。使用索引也可以加快过滤速度
第二,在进行本地筛选时,获取和传输许多记录,并将数据解组到对象中,只是为了扔掉大量记录,这是对带宽和计算资源的浪费。首先要意识到,您无法仅从这段代码中分辨出针对数据库发出的语句。很可能收集所有的过滤、限制和映射,并在调用
collect
时使用所有这些信息来构造匹配的SQL语句(或使用的任何查询语言)并发送到数据库
考虑到这一点,使用streamlike API有很多原因
另一方面,如果您的数据很小,那么使用
流
的方法是有效的。编写这样的流管道是非常可读的(只要你把流说得足够好)。Hibernate和其他ORM通常对编写实体而不是读取更有用,因为它们允许开发人员将特定写入的顺序卸载到框架中,而框架几乎永远不会“出错”
现在,对于读取和报告,另一方面(考虑到我们在这里谈论的是DB),SQL查询可能会更好,因为在这两者之间不会有任何框架,您将能够根据调用此查询的数据库而不是您选择的框架来调整查询性能,这在某种程度上为如何进行调优提供了更大的灵活性。好吧,理想情况下,您的问题应该是-在数据库中执行缩减/过滤操作,还是使用流获取所有记录并在Java中执行它更好? 答案并不直截了当,任何给出“具体”答案的统计数据都不会推广到所有情况 您所说的操作最好在数据库本身中完成,因为这就是DBs的设计目的,可以非常快速地处理数据。当然,通常在关系数据库的情况下,会使用一些“簿记和锁定”来确保独立事务不会导致数据不一致,但即便如此,DBs在过滤数据方面做得相当好,尤其是大型数据集 一个我会