代码之家  ›  专栏  ›  技术社区  ›  yawn

在Spring中并发访问JDBC结果集

  •  1
  • yawn  · 技术社区  · 15 年前

    我正在一个SpringJDBCDAO中处理大量数据。DAO直接返回在有界对象上操作的对象的迭代器 阻塞队列 使用 () 当检索操作在单独的线程中发生时(使用 执行服务 )。

    在这个线程中,我看到了以下行为:检索工作,但对 结果集 导致呼叫挂起。这些电话是

    • iSCODE()
    • ISLAST()

    但不是

    • 其后是()
    • 首先,()
    • ISFILSTATE()

    显然,我需要知道最后一个元素是什么(为了将一个特殊元素插入到阻塞队列中,该队列在迭代器hasNext()方法中产生false)。我可以通过找出 结果集 在将对象放入 阻塞队列 但这感觉有点笨拙。有线程安全的方法来处理结果集吗?

    切换到多线程数据源(我测试了c3pos ComboPooledDataSource )似乎没有帮助。

    注意:这个问题是我首先(错误地)发现的 here

    2 回复  |  直到 15 年前
        1
  •  1
  •   skaffman    15 年前

    我不这么认为 java.sql.ResultSet 是线程安全的,尽管在JavaDoc中没有提到这一点。如果在 ResultSet 从不同的线程导致这些方法调用挂起。

    作为替代方案,我建议将检索线程作为 结果集 ,将行提取出来,然后将数据本身转储到 BlockingQueue . 然后检测结果集的结尾并将您的EOF标记放在队列上变得很简单。

    在JDBC中,迭代非常大的结果集的一般首选机制是使用 fetchSize 性质 java.sql.Statement 尽管这高度依赖于数据库和JDBC驱动程序。我知道Oracle驱动程序尊重这个设置,但不确定其他设置。如果驱动程序决定在给您第一行之前需要将整个结果集提取到内存中,那么无论您做什么,在提取下一行时都无法处理第一行。

        2
  •  1
  •   yawn    15 年前

    正确的解决方案是设置适当的 结果集 类型。默认值 “只输入_forward_” not supported 通过 ISLAST() . 类型 结果集 可以通过使用 准备状态创建者 而不是SQL字符串。 查询() 呼叫A 使用 . 这些实例是通过 准备状态创建者工厂 . 在这样一个工厂里 结果集 (例如) “键入_滚动_不敏感” 可以设置。