我正在从 DB2 表中读取数据并将其转储到文件中。我正在根据列中的值对步骤进行分区。也就是说,如果 column1 的值为“XYZ”,它将进入一个分区,如果 column1 的值为“ABC”,它将进入另一个分区。
问题是第一个分区执行正确,并且数据被写入文件,但是对于第二个分区,我得到“ResultSet is closed”错误。因此产生了 2 个线程,查询执行了两次。我确实得到了 2 个不同的结果集;但是只有一个 ResultSet 被迭代,另一个线程给出了错误。
我正在从 DB2 表中读取数据并将其转储到文件中。我正在根据列中的值对步骤进行分区。也就是说,如果 column1 的值为“XYZ”,它将进入一个分区,如果 column1 的值为“ABC”,它将进入另一个分区。
问题是第一个分区执行正确,并且数据被写入文件,但是对于第二个分区,我得到“ResultSet is closed”错误。因此产生了 2 个线程,查询执行了两次。我确实得到了 2 个不同的结果集;但是只有一个 ResultSet 被迭代,另一个线程给出了错误。
发生错误是因为您不能java.sql.ResultSet
跨多个线程重用 a 。ResultSet
是事务性的,并且与创建它的线程和事务相关联。这也适用于其他类型的 JDBC 资源(语句和连接)。应该跨线程共享的唯一 JDBC 资源是DataSource
. 您还需要确保您正在关闭连接。在某些情况下,WebSphere Application Server 可能能够为您关闭它们,我希望这会导致“ResultSet is closed”错误,但最好的做法是在您使用完 JDBC 资源后立即关闭它们,并且永远不要跨线程缓存它们。在这种情况下,您将需要获取一个连接并在每次通过时执行一个查询。应用程序服务器将通过池化Connection
和缓存PreparedStatement
. 您仍然会有每次重新执行查询的开销,但没有办法解决这个问题。
您对读取器属性branch和分区计划属性parameterForWhereClause感到困惑,后者的值被替换为branch的每个分区值。
在 JSL 中,这样的事情会起作用:
<step id="StepID" start-limit="1">
<chunk checkpoint-policy="item" item-count="10">
<reader
ref="ReaderClass">
<properties >
<property name="parameterForWhereClause" value="#{partitionPlan['branch']}"/>
</properties>
</reader>
<writer
ref="WriterClass">
</writer>
</chunk>
<partition>
<plan partitions="2" threads="2">
<properties partition="0">
<property name="branch" value="XYZ"/>
</properties>
<properties partition="1">
<property name="branch" value="ABC"/>
</properties>
</plan>
</partition>
</step>
(我取出了 step-level 属性,因为它并不明显你真的在使用它。)
因此,理解这一点的方法是 Java 工件的属性名称(如果您有一个没有名称注释值的@BatchProperty,它将只是字段名称)将匹配 JSL 读取器属性的名称。因此,我将 JSL 阅读器属性的名称更改为parameterForWhereClause以匹配您的字段。
由于读取器是分区级工件(对于分区步骤),它可以使用 partitionPlan 替换,这就是我展示的为读取器的parameterForWhereClause属性提供值的方式。