【问题标题】:Spring JPA hibernate -Repeated transactions in the API making it slowSpring JPA hibernate - API 中的重复事务使其变慢
【发布时间】:2018-07-12 10:04:01
【问题描述】:

我正在春季开发 API - JPA - Hibernate 应用程序。 API接收订单列表,需要一一持久化。

控制器方法如下

bulkUpsert(@RequestBody Orders orders){
  for(Order order:orders.getOrders()){
       saveOrUpdateOrder(order);
  }
}

服务方法如下

@Transactional
saveOrUpdateOrder(Order order){
   //do processing and call dao methods to save/update
}

这是我的弹簧配置

<bean id="transactionManager"
      class="org.springframework.orm.jpa.JpaTransactionManager"
      p:entityManagerFactory-ref="entityManagerFactory">
    <property name="defaultTimeout" value="${jdbc.defaultTransactionTimeout}"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>

网页 xml:

 <filter>
    <filter-name>OpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
  </filter>

现在我观察到的问题是,随着通过的订单数量不断增加,完成 API 的时间呈指数级增长。我没有预料到这一点,因为我正在逐一提交订单。 如果前 100 个订单大约需要 10 秒,那么第 900-1000 个订单需要超过 1 分钟。

现在如果我在控制器方法(bulkUpsert)的循环中调用 saveOrUpdateOrder 之后添加 entitymanager.clear(),api 变得很快。

虽然我很高兴问题得到解决,但我很困惑,因为我的理解与发生的事情不符。我期待当事务提交时,它会刷新所有的东西,一切都将重新开始下一次事务.

不是吗?

即使事务提交,实体是否仍保留在会话中?

【问题讨论】:

  • 理论上你是对的。但是 Spring Boot 默认启用 Open EntityManager In View 模式,它为您提供 1 个实体管理器来处理整个请求。这也是为什么你会如此对待你所看到的行为。您可以禁用该模式(在您的application.properties 中将属性设置为false)以获得您期望的行为。但是,这可能会破坏应用程序的其他部分(在不知不觉中)依赖它。

标签: spring hibernate jpa entitymanager


【解决方案1】:

理论上你是正确的,但是默认情况下 Spring Boot 启用 OpenEntityManagerInViewInterceptor 启用 open entitymanager in view pattern。这反过来将您引导到每个请求的单个 EntityManager

这解释了您所看到的行为,因为您希望在每笔交易中获得一个全新的 EntityManager,但重新使用了预先注册的 EntityManager

您可以通过禁用OpenEntityManagerInViewInterceptor 来解决此问题。通过在application.properties 文件中将spring.jpa.open-in-view 设置为false 来执行此操作。但是,这可能会导致其他代码出现问题,这些问题可能在不知不觉中依赖于开放实体管理器的视图行为。

【讨论】:

  • 我也想过Requires_new应该解决这个问题,但它没有。它和以前一样慢。
  • 好吧,我的错。这确实不能解决它,因为单个实体管理器仍然存在。您将有多个事务,但仍然是一个实体管理器。我已将其从答案中删除。
  • 所以我的问题是,即使只有一个 entitymanager 存在,为什么它应该减慢 API 的速度。如果我检查从未随着订单数量的增加而呈指数增长的堆空间......或者是它只影响休眠?
  • 这就是 ORM 的工作原理。这是因为有一个 entitymanager 它放慢了速度。对第一级缓存 (EntityManager) 中的每个对象进行脏检查,并对每个 flush 或对数据库的查询执行此操作。随着您向单个实体管理器添加越来越多的实体,这会变得越来越慢。现在,当您致电clear() 时,您基本上会从该实体管理器中删除所有内容,并且无需进行任何检查。这就是为什么它会很快。
  • 我期待它在事务提交时删除所有内容,因为它会刷新所有内容并同步数据库?
猜你喜欢
  • 2011-08-22
  • 2015-09-13
  • 1970-01-01
  • 2011-04-22
  • 2012-09-03
  • 2023-03-18
  • 1970-01-01
  • 2018-02-04
  • 1970-01-01
相关资源
最近更新 更多