使用Hibernate进行集合缓存

时间:2016-12-27 10:05:03

标签: java spring hibernate caching ehcache

我有一个带有数据库实体的Java / Spring应用程序。 其中一个实体是DataSet。 每个DataSet都可以有一个父DataSet。 父母 - DataSet有多个(OneToMany)孩子。

    @OneToMany(fetch=FetchType.LAZY)
    @IndexColumn(name = "order_id")
    @JoinColumn(name = "parent_dst_id")
    @Fetch(FetchMode.SELECT)
    @Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE)
    public List<DataSet> getChildren()
    {
        return children;
    }

几年后,许多DataSet分组在一些父数据集下。

parentDataset.getChildren().size() // > 200.000

在代码中(我不确定这是否正确)在向父母添加新数据集(调查)时会执行以下行:

surveyDataset.setParent(parentDataset);
parentDataset.getChildren().add(surveyDataset);

直到最近,children根本没有缓存。然后第二个语句导致对数据库进行长时间运行的查询。

最近我们将datasets.children添加到缓存中。这样,一切都很快。

...直到

..添加了另一个子数据集(在同一个父项下!)它再次变得非常慢(即:它再次开始查询数据库)。

我认为缓存正在逐渐被清除或清除,或者这就是再次查询的原因。

另请参阅:http://planet.jboss.org/post/collection_caching_in_the_hibernate_second_level_cache TLDR :“Hibernate不会更新缓存中的集合,只是将其删除。”)

我试图了解日志记录(net.sf.ehcache = DEBUG和org.hibernate.SQL = DEBUG),但这很难。

所以我遇到了几个问题

1)我需要做些什么来防止再次加载所有子数据集(来自新数据集的所有兄弟姐妹)? 2)如何调试缓存中发生的事情?它会驱逐父母吗?还是所有的孩子?正如文章中所解释的那样,它可能会重新加载整个集合。

1 个答案:

答案 0 :(得分:0)

  1. 您可以更改缓存使用情况=&#34;读写&#34;缓存使用情况=&#34;只读&#34;然后在代码中维护驱逐策略。这是管理缓存的最安全的方法,但需要相当多的代码来管理缓存。

  2. 有关调试的方法有两种。

    1. 在hibernate中启用show_sql并查看查询是否正在执行两次,这通常表明hibernate首先尝试检查缓存中的对象并且没有找到并发送第二个查询数据库方式。
    2. 按照本文中的说明记录缓存命中:http://winterbe.com/posts/2009/10/01/how-to-log-hibernate-cache-this/