Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring-Hibernate使用FlushMode提高事务性能_Java_Spring_Hibernate_Entitymanager_Spring Data Jpa - Fatal编程技术网

Java Spring-Hibernate使用FlushMode提高事务性能

Java Spring-Hibernate使用FlushMode提高事务性能,java,spring,hibernate,entitymanager,spring-data-jpa,Java,Spring,Hibernate,Entitymanager,Spring Data Jpa,我正在尝试改进asynk事务方法的性能 在这个任务中,我必须从一个表中读取大约7500条记录,对其进行详细说明,并在另一个表中插入/更新相应的行 我在hibernate中使用spring数据jpa 为了获得可滚动的结果,我将EntityManager注入到我的服务中 下面是如何获得我的ScrollableResult对象: Session session = (Session) em.unwrap(Session.class); ScrollableResults res = s

我正在尝试改进asynk事务方法的性能

在这个任务中,我必须从一个表中读取大约7500条记录,对其进行详细说明,并在另一个表中插入/更新相应的行

我在hibernate中使用spring数据jpa

为了获得可滚动的结果,我将
EntityManager
注入到我的服务中

下面是如何获得我的
ScrollableResult
对象:

Session session = (Session) em.unwrap(Session.class);
        ScrollableResults res = session.createQuery("from SourceTable s")
                .setCacheMode(CacheMode.IGNORE)
                .scroll(ScrollMode.FORWARD_ONLY);


while (res.next()){
.... // em.flush() called every 40 cycles
}
根据结果循环大约需要60秒

这里是瓶颈。如果在我的循环中执行一个简单的查询:

query = em.createQuery("from DestTable d where d.item.id = :id", DestTable.class);

 while (res.next()){
     query.setParameter("id", myId).getSingleResult();     
 }
执行时间变慢x10。。大约需要600秒

我试图修改我的
会话
或我的
EntityManager
的参数:
会话.setFlushMode(FlushModeType.COMMIT)
em.setFlushMode(FlushModeType.COMMIT)

它提高了性能并删除了手动刷新()方法。工作在40秒内完成

因此,我的问题是:

  • session
    enityManager
    上调用
    setFlushMode
    有什么区别
  • 为什么
    setFlushMode(FlushModeType.COMMIT)以这种方式提高性能,而我不能仅通过手动刷新entityManager来获得相同的性能

问题在于默认刷新模式为
FlushModeType.AUTO
。在自动刷新模式下,Hibernate将在每次查询之前刷新(仅查询,不查找操作)。这意味着在上面的示例中,默认情况下,每次调用
getSingleResult()
时,Hibernate都会刷新。之所以这样做,是因为您所做的更改可能会影响查询结果,因此Hibernate希望您的查询尽可能准确,并首先刷新


在第一个示例中,您没有看到性能受到影响,因为您只发出一个查询并滚动浏览它。我找到的最好的解决方案是您提到的,就是将刷新模式设置为
COMMIT
。在
会话上调用
setFlushMode
与在
EntityManager上调用
setFlushMode

之间应该没有区别。一个可能的区别是,在会话上使用它只会覆盖当前事务的flush属性,而在EntityManager上设置它时,所有事务的属性都会被设置。可能吗?不,EntityManager和会话都绑定到第一级上下文。它们具有相同的生命周期。如果您能够在SessionFactory或EntityManagerFactory上设置刷新模式,则可能是这样,但据我所知,没有办法做到这一点。hibernate flush的问题是,这会触发actionqueue的生成,然后对其进行处理。刷新时,管理的实体越多,问题就越明显。Hibernate检查每一次!更改的实例。因此,如果您知道您的代码对查询列表没有影响,那么最后一次刷新(提交时)的解决方案可以解决这个问题。另一种选择是在目标查询之前调用entitymanager上的clear,以使刷新循环尽可能小。一个副作用是记忆足迹变小。