关于 Hibernate加载树形结构的数据如何用上二级缓存问题-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

关于 Hibernate加载树形结构的数据如何用上二级缓存问题

2016-03-04 14:37:44 2475 1

经常有树形结构的数据保存在一张二维表中,例如组织架构,多级菜单等。一般是在一张表中使用ID,PID作关联。我项目中的是这样一个树形菜单:

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "Menu")
@Table(name = "DDT_MENU", schema = "CBA", uniqueConstraints = @UniqueConstraint(columnNames = "ENNAME"))
public class Menu implements java.io.Serializable {
     
    private static final long serialVersionUID = 1L;
    private Long id;
    private EMenu enname;
    private String zhname;
    private Long pid;
    private String grade;
     
    private Menu parent;
    private Set<Menu> children=new TreeSet<Menu>();
     
    public Menu() {
    }

下面是关联配置:


@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PID", nullable = true)
public Menu getParent() {
    return parent;
}
 
@OneToMany(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, mappedBy = "pid")
public Set<Menu> getChildren() {
    return children;
}

这些数据由于很修改少,访问频繁,因此很适合放在缓存中。

下面是EhCache配置:

  <cache name="Menu"   
       maxElementsInMemory="100"
       eternal="false"
       timeToIdleSeconds="120"
       timeToLiveSeconds="120"
       overflowToDisk="false"
       diskPersistent="false"
       diskExpiryThreadIntervalSeconds="120"
       memoryStoreEvictionPolicy="LRU"  
/>

我在程序中用递归方式获得整个树形结构的数据,观察后台Hibernate输出的语句,一直都没使用上缓存。根据Hibernate使用缓存的机制:
1) Hibernate首先根据这些查询信息组成一个Query Key,Query Key包括条件查询的请求一般信息:SQL, SQL需要的参数,记录范围(起始位置rowStart,最大记录个数maxRows),等。   2) Hibernate根据这个Query Key到Query缓存中查找对应的结果列表。如果存在,那么返回这个结果列表;如果不存在,查询数据库,获取结果列表,把整个结果列表根据Query Key放入到Query缓存中。   3) Query Key中的SQL涉及到一些表名,如果这些表的任何数据发生修改、删除、增加等操作,这些相关的Query Key都要从缓存中清空。
来看,也确实使用不上,因为每次递归getChildren()的查询条件不同。现在不知道咋搞,请各位大侠不吝赐教。

取消 提交回答
全部回答(1)
  • 爵霸
    2019-07-17 18:52:17

    经过我仔细的调试,发现使用配置对象之间的关联关系(@OneToMany )得到的关联对象并不会放到二级缓存中。例如上述例子中,我遍历整棵树,在递归得到孩子菜单时是通过Menu类的getChildren()方法,调用此方法得到的孩子菜单对象hibernate并不会放到二级缓存中。因此,为了使用上缓存,我自己写了另外一个方法findMyChildren(),代码如下:

    @SuppressWarnings("unchecked")
    public HashSet<Menu> findMyChildren(Menu m) {
        DetachedCriteria dc = DetachedCriteria.forClass(Menu.class);
        dc.add(Restrictions.eq("pid", m.getId()));
        List<Menu> menus = hibernateTemplateUseCache.findByCriteria(dc);
        HashSet<Menu> menusSet = new HashSet<Menu>(menus);
        return menusSet;
    }

    然后递归取得孩子菜单时使用此方法,此方法返回的孩子菜单都会被保存到二级缓存中,以后访问时会直接从缓存中拿。由于项目的菜单在程序运行过程中不会被修改,因此只需从数据库加载一次。于是修改EhCache配置:

      <cache name="Menu"   
           maxElementsInMemory="200"
           eternal="true"
           timeToIdleSeconds="0"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           diskPersistent="false"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU"  
    />

    这样一来,就达到了树形结构数据永远去缓存中取的目的。

    0 0
相关问答

1

回答

Hibernate中加载数据用什么方法啊?

2022-08-16 20:53:33 21浏览量 回答数 1

1

回答

Hibernate中如何将对象写入数据库呢?

2022-08-16 20:53:25 21浏览量 回答数 1

1

回答

hibernate连接数据库问题??报错

2020-06-08 16:58:15 340浏览量 回答数 1

0

回答

关于Hibernate的二级缓存配置

2016-06-02 15:13:38 1611浏览量 回答数 0

1

回答

hibernate 映射和数据传输的问题

2016-03-04 09:44:22 1664浏览量 回答数 1

1

回答

关于Hibenate数据库查询的问题

2016-02-19 17:53:55 1682浏览量 回答数 1

1

回答

hibernate的关系映射和无关系型数据库

2016-06-02 13:52:33 1833浏览量 回答数 1

0

回答

说下Hibernate的缓存机制

2021-11-01 14:58:57 357浏览量 回答数 0

1

回答

关于hibernate一级缓存问题

2016-03-17 09:13:04 1703浏览量 回答数 1

1

回答

关于hibernate一级缓存问题

2016-02-21 17:46:47 1579浏览量 回答数 1
+关注
2
文章
9426
问答
问答排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载