gpt4 book ai didi

hibernate - 避免使用缓存 Hibernate 关联或缓存集合作为整体进行 n+1 选择

转载 作者:行者123 更新时间:2023-12-02 23:54:53 25 4
gpt4 key购买 nike

我有一对多关系:父记录与 n 子记录。这些记录经常使用且只读,非常适合缓存。

这是我的 Hibernate 映射的近似值:

`<class name="Parent" table="Parent>
<cache usage="read-only"/>
<id name="primary_key"/>
<property name="natural_key"/>

<set name="children" lazy="false" fetch="join">
<cache usage="read-only"/>
<key-column name="parent_id"/>
<one-to-many class="Child"/>
</set>
</class>

<class name="Child" table="Child">
<cache usage="read-only"/>
<id name="primary_key"/>
<property name="parent_id"/>
</class>`

我经常通过自然键而不是主键获取父级,因此我需要启用查询缓存才能利用二级缓存(我使用ehcache)。

问题如下:当我获取父项并在查询缓存中命中时,它变成“按主键获取”查询。这对于我的一对多的“一”端来说很好。如果在缓存中找不到父级,则从数据库中获取。如果在缓存中找不到我的 n 个子记录,Hibernate 将使用 n 个后续选择查询来获取它们。 N+1选择问题。

我想要的是一种缓存子对象集合的方法,以parent_id为键。我希望 Hibernate 在缓存中作为一个整体来查找我的集合,而不是作为一堆单独的记录。如果找不到集合,我希望 Hibernate 使用 1 个 select 语句来获取集合 - 获取所有带有parent_id=x 的子项。

对 Hibernate + ehcache 的要求是否过高?

最佳答案

我找到了自己的答案 - 可以配置 Hibernate + ehcache 来执行我上面描述的操作。

通过将我的 Child 声明为值类型而不是实体类型(我相信这些是 Hibernate 社区使用的术语),我基本上可以将我的 Child 视为 Parent 的组件而不是单独的实体。这是我修改后的映射的示例:

<class name="Parent" table="Parent">
<cache usage="read-only"/>
<id name="primary_key"/>
<property name="natural_key"/>

<set name="children" lazy="false" fetch="join" table="Child">
<cache usage="read-only"/>
<key-column name="parent_id"/>
<composite-element class="Child">
<property name="property1" column="PROP1" type="string">
<property name="property2" column="PROP2" type="string">
</composite-element>
</set>
</class>

在此配置下,我的 Child 对象的行为与以前略有不同 - 现在没有为 Child 定义单独的主键,没有共享引用,也没有可为空的字段/列。请参阅Hibernate docs了解更多详细信息。

我的父级和子级都是只读的,我真的只想通过父级访问子级的实例 - 我不会独立于父级使用子级,因此值类型处理非常适合我的用例.

对我来说最大的胜利是集合在我的新配置下的缓存方式。集合缓存现在将我的集合作为一个整体进行缓存,以parent_id 为键。我的收藏中的部分(但不是全部)不再可能位于缓存中。该集合作为一个整体被缓存和驱逐。更重要的是,如果 Hibernate 在二级缓存中查找我的集合但未命中,它会通过单个选择查询从数据库中获取整个集合。

这是我的 ehcache 配置:

 <ehcache>
<cache name="query.Parent"
maxElementsInMemory="10"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="0"
timeToLiveSeconds="43200"
</cache>
<cache name="Parent"
maxElementsInMemory="10"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="0"
timeToLiveSeconds="43200"
</cache>
<cache name="Parent.children"
maxElementsInMemory="10"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="0"
timeToLiveSeconds="43200"
</cache>
<ehcache>

希望这个例子对其他人有帮助。

关于hibernate - 避免使用缓存 Hibernate 关联或缓存集合作为整体进行 n+1 选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3783681/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com