Java Hibernate是否支持同时获取数据?

Java Hibernate是否支持同时获取数据?,java,hibernate,jpa,orm,concurrency,Java,Hibernate,Jpa,Orm,Concurrency,我理解这是一个困难的问题,因为它不仅依赖于hibernate,而且还依赖于我们使用它的特定方式。 我们在应用程序中使用Hibernate4,可能是错误的,但事实就是这样 因此,我们加载一个完整的类层次结构,在一个大语句中包含连接的子类表,并以150K行的顺序将其转换为对象 因为对象有很多字段要设置(~100),所以我们希望并行化循环,该循环迭代结果集并获取单个行。这在Hibernate中可能吗?Hibernate是否已经从数据库接收到了所有结果,并且可以使用这些数据来创建对象,这样我们就可以使用

我理解这是一个困难的问题,因为它不仅依赖于hibernate,而且还依赖于我们使用它的特定方式。 我们在应用程序中使用Hibernate4,可能是错误的,但事实就是这样

因此,我们加载一个完整的类层次结构,在一个大语句中包含连接的子类表,并以150K行的顺序将其转换为对象

因为对象有很多字段要设置(~100),所以我们希望并行化循环,该循环迭代结果集并获取单个行。这在Hibernate中可能吗?Hibernate是否已经从数据库接收到了所有结果,并且可以使用这些数据来创建对象,这样我们就可以使用多线程来加快获取大型结果集的速度

这有意义吗?还是更改数据结构和映射以消除多表联接更好

实际上,加载150K这些对象需要一分钟或0.3毫秒/个实体。我们有更简单的表和更多的条目,以0.02 ms/entity的速度加载一个数量级。在初始化阶段之后,我们不会加载其他实体,整个数据库需要5分钟以上的时间

如果我们通过不向DB公开类层次结构来删除连接,并切换到基于组合的数据结构,那么我们可能会得到更简单的表负载,而不是复杂的连接,代价是多个表负载,而不是一个将这些负载组合成一个的连接


但是问题仍然存在:如果我们有这么多行要加载,并且在填写每个对象的字段时相应地要调用许多setter,那么这可以并行完成吗?

不,Hibernate中没有这样的事情

但是,如果您提到的数据集彼此独立,则可以将不同会话(事务)中的每个数据集同时加载到不同线程中(每个数据集一个线程和一个会话)。然后从所有线程中获取结果


这种方法的另一个好处是,您还可以并行化数据集的查询执行。

如果您希望将所有实体提取到二级缓存中,那么您可能确实希望提取所有这些数据,但我认为这不是一个好主意

我认为应该只缓存访问量最大的数据,而不是整个条目。这样,缓存将需要更少的空间,并且不需要一次获取整个结果集

如果您真的想获取所有这些数据,我建议使用另一种方法

您可以使用Java并发在多个线程上并行获取,因此您可以设置一个EexcutorService,它接受一个可调用项并尝试批量获取条目


如果有N个处理器,则可以使用N个工作线程来执行此操作。将根实体ID间隔除以N,可以获得N个子间隔。每个工作线程将处理一个这样的间隔,并批量加载数据。这样你就不需要了;不必同步N个工作线程,以避免两次加载相同的数据。由于ID通常都会被索引,因此按根实体ID对条目进行排序,并从最后处理的ID开始获取批处理,可能会显著加快加载速度。

并行获取策略是一种可能,但IMHO会增加系统的复杂性。同时,目前很难判断这种解决方案的可伸缩性。我的建议是(如果您有时间的话)检查数据对象并删除不需要的连接和数据。JPA中的问题是EntityManager设计为仅在单个线程中使用。如果希望并行加载数据,则需要使用不同的EntityManager将工作划分为不同的事务。但是,如果您希望最终将所有数据都放在一个entitymanager中,则可以使用EM.merge()将加载的实体附加到最后一个EM中。但这可能会执行更多的SQL查询,而不是在一个线程中获取数据,因此加载速度会更慢。没错,但问题是,在一个Hibernate会话中,您真的需要如此大量的数据吗?如果是,则在多个线程中预加载二级缓存中的所有内容,然后使用最终的EM读取这些内容,将产生更少的查询量(在理想情况下,
EM.merge()
将从二级缓存中读取所有内容)。但是,即使没有合并,如果
SomeEntity
的关联在二级缓存中,像
select*fromsomeentity
这样的查询执行的额外查询也会少得多。