我的设置是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行。
为什么以下提取不会返回下一个记录块?
答案 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游标没有意义。