在hibernate中有效滚动:session.evict vs session.clear vs CacheMode.IGNORE

时间:2013-04-13 09:36:54

标签: java hibernate

当我们必须通过从DB滚动适当的结果来构建大型文件报告时,考虑一个典型的任务。 ORM框架是Hibernate。 我们知道,有三种方法,如何避免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 个答案:

答案 0 :(得分:4)

  • CacheMode.IGNORE与您的问题无关。它是关于二级缓存,而不是会话缓存。
  • 如果在没有evict()CascadeType.DETACH的情况下配置关系,则
  • CascadeType.ALL不会驱逐相关实体。这意味着:
    1. 没有级联驱逐的相关实体将在内存中累积
    2. 每次迭代都会重新加载具有级联驱逐的相关实体,即使它们是相同的
  • 使用clear()的方法是最佳选择:
    1. 调用时,它会从会话缓存中驱逐所有实体
    2. 每次迭代都不会调用它,因此您可以利用相关实体的会话缓存