sql执行后,字符串引用保存在堆中

问题描述 投票:0回答:1

最近我遇到了一个非常奇怪的内存泄漏问题。 如果有人帮助我解决它,我将不胜感激。

public Mono<Boolean> insertOrders(List<ClientOrder> orders) {
    if (orders.isEmpty()) {
      return Mono.just(true);
    } else {
      var sqlBuilder = new StringBuilder().append(OrderQueries.INSERT_ORDERS_START);
      for (var i = 0; i < orders.size(); i++) {
        var order = orders.get(i);
        sqlBuilder.append(String.format(
          OrderQueries.INSERT_ORDERS_PARAMS,
          order.getUserId(),
          order.getUserName(),
          order.getCustomerEmail(),
          order.getCustomerMobile(),
          order.getAmount(),
          order.getCreateDate(),
          order.getStatusChangeDate(),
          i == orders.size() - 1 ? ';' : ','
        ));
      }
      return this.databaseClient.sql(sqlBuilder.toString()).fetch().rowsUpdated()
        .doOnError(log::error)
        .map(rows -> rows == orders.size());
    }
  }

当我执行堆转储时,我可以看到存储了对查询字符串的引用,并且 GC 永远不会清除 sql 查询。

java spring-boot r2dbc
1个回答
0
投票
  OrderDao(ConnectionFactory connectionFactory){
    this.databaseClientNamed = DatabaseClient.builder().connectionFactory(connectionFactory).namedParameters(true).build();
    this.databaseClient = DatabaseClient.builder().connectionFactory(connectionFactory).namedParameters(false).build();
  }

正如 @ControlAltDel 提到的,问题在于 spring 缓存 sql 语句。因此,由于我没有针对这种特殊情况使用准备好的语句,并且查询非常大,有 55K 插入。在这种特殊情况下的解决方法是使用另一个没有namedParamenters(它正在缓存结果)的数据库客户端,我不向任何人推荐这个解决方案。但这对于任何在堆中找到一些 sql 查询的人来说都是有好处的。 NamedParameterExpander 正在缓存您执行的所有内容。

© www.soinside.com 2019 - 2024. All rights reserved.