当前位置: 首页 > 知识库问答 >
问题:

如何从jdbc结果集返回java8流[duplicate]

仲孙毅
2023-03-14

为了最大限度地利用java8流和Spring4,我在来自Springs jsdbRestTem板的JDBC结果集上使用了流API,如下所示(代码缩短并简化):

public <T> T consumeResultStream(
    String query, 
    Function<Stream<String>, T> extractorFunction
) {
    return jdbcTemplate.query(
        query, 
        resultSet -> {
            Spliterator<String> spliterator = 
                Spliterators.spliteratorUnknownSize(
                    new Iterator<String>() {
                      @Override public boolean hasNext() {
                        return !resultSet.isAfterLast();
                      }
                      @Override public String next() {
                        String result = resultSet.getString(0);
                        resultSet.next();
                        return result;
                      }
                    }, 
                    Spliterator.IMMUTABLE);
           resultStream = StreamSupport.stream(
               spliterator, /*parallel*/ false);
       }
       return extractorFunction.apply(resultStream);
    });
}

这似乎很有效。客户端可以像这样使用流Api,而不用担心jdbc类

List<T> myResult = consumeResultStream("SELECT ...", stream -> 
    stream.filter((String s) -> ...)
        .map(String s -> toT(s))
        .collect(toList()));

但是,当我重构(尝试将流提供给客户端方法)时,像这样:

    final Stream<String> stream = 
        jdbcTemplate.query(query, resultSet -> {
          // ... same as above
          return resultStream;
        });
    return extractorFunction.apply(stream);

我明白了

org.springframework.jdbc.InvalidResultSetAccessException: 
  The object is already closed [90007-199]

因此,数据似乎只能在jdbc模板中读取。query()方法。是否有一种干净的方法可以绕过这个问题,返回来自DB的元素的惰性流?假设具体化结果和流式传输由于结果的大小而不是一个选项(尽管分页可能是更好的模式)。

共有1个答案

慕凌龙
2023-03-14

JdbcTemboard不处理调用之外的事务,这与SpringJPA特性相反。
要不允许关闭DB连接,请从客户端打开一个事务来操作返回的惰性结果。
注释它@事务性一般就足够了:

@Transactional
public void findLazyData(){
   Stream<String> result = dataAccessService.find(...);
   // where find() contains the JdbcTemplate invocation
}

注意包的来源:org.springframework.transaction.annotation.Transactional

 类似资料:
  • 问题内容: 我正在使用JDBC来实现非常简单的数据库连接。 我已经创建了连接/语句并执行了查询。我在调试器中检查语句的查询对象,以确认它正在发送正确的查询。然后,我再次检查了数据库中的查询(直接从调试器复制),以确保其返回数据。但是,返回的结果集在.next()上给出false 这里有我遗漏的常见陷阱吗? 还有myDB类(一个简单的包装程序,使我可以将连接/语句代码放入任何项目中) 编辑:根据建议

  • 问题内容: 我正在尝试创建一种方法,从中可以查询数据库并检索整个表。 目前,如果我使用这些数据只是正常工作 中 的方法。但是,我希望该方法返回结果。 我正在了解当前代码。 我该如何实现? 问题答案: 您永远不要通过公共方法来回避。这很容易导致资源泄漏,因为您不得不保持语句和连接打开。关闭它们将隐式关闭结果集。但是,将它们保持打开状态将导致它们悬而未决,并且当它们打开过多时,将导致数据库用尽资源。

  • 我很好奇是否可以在以下情况下使用orElseThrow(),或者是否有更Java的8种方法可以将其等效为1行?

  • 主要内容:ResultSet类型,ResultSet的并发性,浏览结果集,查看结果集,更新结果集SQL语句执行后从数据库查询读取数据,返回的数据放在结果集中。 语句用于从数据库中选择行并在结果集中查看它们的标准方法。 接口表示数据库查询的结果集。 对象维护指向结果集中当前行的游标。 术语“结果集”是指包含在对象中的行和列数据。 接口的方法可以分为三类: 浏览方法:用于移动光标。 获取方法:用于查看光标指向的当前行的列中的数据。 更新方法:用于更新当前行的列中的数据。 然后在基础数据库中更新数

  • 问题内容: 我正在使用CsvJdbc(它是用于csv文件的JDBC驱动程序)来访问csv文件。我不知道csv文件包含多少列。如何获得列数?是否有任何JDBC函数?我在java.sql.ResultSet中找不到任何方法。 为了访问该文件,我使用类似于CsvJdbc网站上示例的代码。 问题答案: 您可以从ResultSetMetaData获取列号:

  • 有一个简单的: 以及任务对象的列表。如何通过使用获得每个作为的列表。我试过这个: 但它返回