为什么从数据库游标中获取始终返回与MyBatis和Spring Transaction相同的结果集

时间:2015-02-12 22:44:54

标签: postgresql cursor mybatis spring-transactions

我的设置是Postgres数据库,它通过JDBC驱动程序连接到Tomcat服务器(负责连接池),它再次通过JNDI将此数据源提供给Spring应用程序。

在java应用程序中,我使用MyBatis和MyBatis-Spring来查询数据库。 现在我想使用游标在页面中翻页,如下面的简单示例http://www.postgresql.org/docs/9.3/static/sql-fetch.html所示。

由于游标需要在DB事务中运行,因此我使用Spring DataSourceTransactionManager提供的@transactional注释注释了相关方法(参见http://mybatis.github.io/spring/transactions.html

这是疯狂的部分开始的地方。在运行时,MyBatis映射器查询的每个FETCH FORWARD 1000 FROM CURSOR都会返回一个相同的结果集。因此,似乎每次调用时光标位置都会回滚。因此,它将每次返回表格的前1000行。

为什么以下提取不会返回下一个记录块?

1 个答案:

答案 0 :(得分:0)

我发现MyBatis使用的缓存机制在我看来并不是很聪明https://mybatis.github.io/mybatis-3/configuration.html

实际上,MyBatis默认会缓存会话期间执行的所有查询。会话表示事务或每个连接。所以在AutoCommit上这没问题。但不能与游标一起使用,其中fetch语句在事务中不会发生变化

因此,一旦从游标中获取了DB中的第一个数据,结果就会缓存在内存中,并且不会向DB查询后续的提取。

解决方案是mybatis-config.xml

中的以下行
<setting name="localCacheScope" value="STATEMENT"/>

因此本地会话将仅用于语句执行,不会在对同一SqlSession的两次不同调用之间共享数据。

对我来说,这似乎是一个错误,因为默认的缓存范围对DB游标没有意义。