2015-10-11 59 views
1

我正在使用主要读取和某些更新来依赖缓存的应用程序。使用Spring,Hibernate和Ehcache缓存整个数据库

我使用的技术堆栈是Spring + Hibernate + Ehcache。 我需要使用缓存为请求提供服务,而不是根本访问数据库。 我遵循的方法是使用查询(如getSession().createCriteria(<Entity>.class).list())在应用程序启动时缓存所有数据,然后使用session.get()调用请求Hibernate查找实体,以便它使用二级缓存来解析。

我看到的一个挑战是我的实体类有很多收集和关联属性(多对多,多列,一对多,一对一)。

我有这样一个缓存两种方法:

  1. 保留所有关系,因为预先抓取。在启动时,缓存将充满包含左外连接的大查询的数据。 我担心加载数据会导致不必要的长时间运行查询返回多行。

  2. 将关系保持为懒惰并迭代所有行并呼叫.getSetOf<Entity>加载相关实体。 我担心我将在启动时虚拟迭代所有数据,我不确定这是否是一种好的做法。

由于休眠的关联是使用组合物和外键相关联,并且没有被存储为单独的ID,这种关联的装载/集合似乎是开销。

我希望有不同缓存区域中的表数据,其外键关系只是ID(不是组合/集合)。我会在不同区域缓存所有这些实体,并且会在运行时通过迭代这些区域来合并结果。

任何人都可以提出我应该遵循什么方法?如果有其他方法,建议。

回答

0

我正在研究一个有技术堆栈的项目spring + hibernate + hazelcast。我正在使用休眠二级缓存也。我们也在服务器启动时将数据加载到缓存中。 根据我,你不应该做一个实体的所有集合,因为它使对象非常沉重。我们正在使用混合的方法。根据需要,我们的一些集合是渴望的,有些是懒惰的。如果你的集合有非常大的数据,那么就让它懒,否则就会急切。 还有一两件事,我们都在做,我们使用LEFT JOIN FETCH在查询其加载的集合也如果集合定义lazy.For如: -

SELECT DISTINCT userInfo FROM UserInfo userInfo 
LEFT JOIN FETCH userInfo.userRoles 
LEFT JOIN FETCH userInfo.regions 
LEFT JOIN FETCH userInfo.countries 

在我的实体的UserInfo,我做了区域渴望(因为地区数量较少)和国家懒惰(因为国家数量更多)。现在我的这个查询仍然返回满载国家和地区的userInfo对象。并且由于左连接提取没有多个查询得到执行。

我希望这可以帮助你。

+0

感谢您的回复。关于何时需要向userRole Collection添加角色(比如userInfo.getuserRoles()。add(new UserRole()))添加它时,hibernate会使集合失效。下一次使用userInfo.getUserRoles()时,它会再次查询Db。任何可以处理的方式。即如何避免缓存失效? – ankurlu

+0

在失效的情况下,我们正在刷新缓存。是的,你是对的,我们将再次击中数据库以获取更新的UserInfo。 –

+0

您是否认为使用Core Ehcache API是一种去那里的方法。我将使用EHcache API在启动时缓存数据,并且具有添加/删除/修改缓存的灵活性,而不依赖于Hibernate来实现这一点。 – ankurlu

0

从描述中不清楚应用程序是否控制对数据库的访问。

  • 如果不是,那么performance documentation指出您有风险陈旧的数据。你在这种情况下做什么?
  • 如果是这样,并且只有当你真的需要最小化数据库命中的数量,那么我不会使用Hibernate或Ehcache。除了最初的加载之外,没有太多的ORM在我看来并没有成为Hibernate的一个用例。我会在启动时使用Spring JDBC进行批量选择。这将减少调用次数和可能出现的内存不足异常(“正常”选择语句引用其读取的数据,因此,当您通过记录获得更多参考资料时,将无法进行GC检查)。它还减少了1个负担的技术堆栈。您可以在更改状态后立即更新缓存和数据库。您可能需要考虑交易范围。左连接可以在你的映射器中处理。我也会放弃OO方法并使用数组或数据图。仅仅为了它而封装每个数据组的数据可能是矫枉过正的(内存消耗,cpu,...)。特别是全负载需求让我觉得这里没有很多交互发生。并放弃Ehcache。如果你真的需要最小化你的数据库调用,你可以把所有东西都放在Map中,因为不需要驱逐策略。

只是要说清楚,我不是反OO或休眠或Ehcache。我只是想知道他们是否适合您的(有限)描述。

相关问题