首页 > 解决方案 > 使用 JPA 将包括关系在内的整个表加载到内存中

问题描述

我必须处理分布在 20 个表中的大量数据(总计约 500 万条记录),并且我需要有效地加载它们。

我正在使用 Wildfly 14 和 JPA/Hibernate。

由于最后,每条记录都将被业务逻辑使用(在同一个事务中),我决定通过简单的方式将所需表的全部内容预加载到内存中:

em.createQuery("SELECT e FROM Entity e").size();

之后,每个对象都应该在事务中可用,因此可以通过以下方式使用:

em.find(Entity.class, id);

但这在某种程度上不起作用,仍然有很多对数据库的调用,特别是对于关系。

我怎样才能有效地加载所需表的全部内容,包括关系,并确保我得到了一切/不会有进一步的数据库调用?

我已经尝试过的:

需要注意的一件事是数据是不可变的(至少在特定时间),也可以在其他事务中使用。

编辑:

@Singleton我的计划是在一个bean中加载和管理整个数据。但我想确保以最有效的方式加载它,并确保加载了整个数据。当业务逻辑使用数据时,应该不需要进一步的查询。在特定时间(ejb 计时器)之后,我将丢弃整个数据并从数据库重新加载当前状态(始终是整个表)。

标签: javahibernatejpajakarta-eewildfly

解决方案


请记住,您可能需要 64 位 JVM 和大量内存。看看Hibernate 2nd Level Cache。由于我们没有您的代码,因此需要检查一些事项:

  1. @Cacheable注释将提示 Hibernate,以便实体可缓存
  2. 将二级缓存配置为使用 ehcache 之类的东西,并将最大内存元素设置为足够大以适合您的工作集
  3. 确保您不会在代码中意外使用多个会话。

如果您需要以这种方式处理事物,您可能需要考虑更改您的设计,使其不依赖于将所有内容都保存在内存中,不使用 Hibernate/JPA,或者不使用应用服务器。这将使您更好地控制事情的执行方式。这甚至可能更适合 Hadoop 之类的东西。如果没有更多信息,很难说哪个方向最适合您。


推荐阅读