java - 使用 JPA 将包括关系在内的整个表加载到内存中
问题描述
我必须处理分布在 20 个表中的大量数据(总计约 500 万条记录),并且我需要有效地加载它们。
我正在使用 Wildfly 14 和 JPA/Hibernate。
由于最后,每条记录都将被业务逻辑使用(在同一个事务中),我决定通过简单的方式将所需表的全部内容预加载到内存中:
em.createQuery("SELECT e FROM Entity e").size();
之后,每个对象都应该在事务中可用,因此可以通过以下方式使用:
em.find(Entity.class, id);
但这在某种程度上不起作用,仍然有很多对数据库的调用,特别是对于关系。
我怎样才能有效地加载所需表的全部内容,包括关系,并确保我得到了一切/不会有进一步的数据库调用?
我已经尝试过的:
- FetchMode.EAGER:仍然有太多的单选/对象图太复杂
- EntityGraphs :与 FetchMode.EAGER 相同
- Join fetch statements:迄今为止最好的结果,因为它同时填充了与引用实体的关系
- 2nd Level / Query Cache:不工作,可能与相同的问题
em.find
需要注意的一件事是数据是不可变的(至少在特定时间),也可以在其他事务中使用。
编辑:
@Singleton
我的计划是在一个bean中加载和管理整个数据。但我想确保以最有效的方式加载它,并确保加载了整个数据。当业务逻辑使用数据时,应该不需要进一步的查询。在特定时间(ejb 计时器)之后,我将丢弃整个数据并从数据库重新加载当前状态(始终是整个表)。
解决方案
请记住,您可能需要 64 位 JVM 和大量内存。看看Hibernate 2nd Level Cache。由于我们没有您的代码,因此需要检查一些事项:
@Cacheable
注释将提示 Hibernate,以便实体可缓存- 将二级缓存配置为使用 ehcache 之类的东西,并将最大内存元素设置为足够大以适合您的工作集
- 确保您不会在代码中意外使用多个会话。
如果您需要以这种方式处理事物,您可能需要考虑更改您的设计,使其不依赖于将所有内容都保存在内存中,不使用 Hibernate/JPA,或者不使用应用服务器。这将使您更好地控制事情的执行方式。这甚至可能更适合 Hadoop 之类的东西。如果没有更多信息,很难说哪个方向最适合您。
推荐阅读
- sdk - Genexus Extensions SDK - 如何为 Genexus Server 开发扩展?
- android - 如何使用 Flutter 创建自定义 3D 框?
- python - 如何将 cv2 矩形边界框合并为多边形?(不是重叠/阈值)
- javascript - Javascript - 在特定网站上多次注入代码
- amazon-web-services - s3 从 s3 存储桶前缀中检索所有删除标记版本
- java - Jakarta EE 兼容的应用程序服务器版本
- python - 我想用假人做一个链表但是为什么代码是反向打印的!!。这是我的代码
- python - 使用 python 和正则表达式 BeautifulSoup lxml 查找文本
- flutter - 您如何通过特定值找到某个地图条目?
- android - 如何优化滞后的 JetPack Compose 布局