2

考虑一个典型的任务,当我们必须通过滚动数据库中的适当结果来构建大文件报告时。ORM 框架是Hibernate. 我们知道,有 3 种方法可以避免OutOfMemoryException这种模式:

  1. 使用session.evict(...)

    ScrollableResults customers = session.createQuery("from Customers order by id").scroll(ScrollMode.FORWARD_ONLY);
    while (customers.next()) {
        Customer customer = (Customer) customers.get(0);
        addDataToReport(customer);
        session.evict(customer);
    }
    
  2. 使用session.clear()

    ScrollableResults customers = session.createQuery("from Customers order by id").scroll(ScrollMode.FORWARD_ONLY);
    int i = 0;
    while (customers.next()) {
        Customer customer = (Customer) customers.get(0);
        addDataToReport(customer);
        if ( ++i % 1000 == 0) session.clear();
    }
    
  3. 使用CacheMode.IGNORE

    ScrollableResults customers = session.createQuery("from Customers order by id").setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY);
    while (customers.next()) {
        Customer customer = (Customer) customers.get(0);
        addDataToReport(customer);
    }
    

所以,问题是:对于上述目的,这些方法中哪一种更好(在性能方面)?或者可能有更有效的其他方法?

4

1 回答 1

4
  • CacheMode.IGNORE与你的问题无关。这是关于二级缓存,而不是会话缓存。
  • evict()CascadeType.DETACH如果关系配置为不带or ,则不会驱逐相关实体CascadeType.ALL。代表着:
    1. 没有级联驱逐的相关实体将在内存中累积
    2. 具有级联驱逐的相关实体将在每次迭代时重新加载,即使它们相同
  • 因此,使用 with 的方法clear()是最好的选择:
    1. 调用时,它会从会话缓存中驱逐所有实体
    2. 它不会在每次迭代时调用,因此您可以利用相关实体的会话缓存
于 2013-04-13T09:51:39.673 回答