为什么即使禁用缓存,iBATIS也会产生陈旧的结果?

时间:2015-03-31 16:08:21

标签: java mysql spring caching ibatis

我有一个Web应用程序,我一直在使用Spring Data从iBATIS 2慢慢迁移到JPA。

在大多数情况下,事情进展顺利,我一次只为一个域对象迁移DAO。但是,最近引起我注意的一个问题是,网站的某些部分正在显示陈旧的结果列表。

例如,我有一个“票证”部分,其中显示了打开票证列表,并允许您在不同页面上查看特定票证。当我创建新票证时,我可以正确地在其特定页面上查看该票证。但是,打开的票证列表似乎在一段时间后才会显示此新票证。

我试图排除的事情:

  • 即使在禁用了MySQL查询缓存的系统上,我也看到了这个问题
  • 即使我在iBATIS配置中设置cacheModelsEnabled="false",我也会看到此问题。
  • 即使我从sqlMap文件中完全删除<cacheModel>元素和cacheModel="x"属性,我也会看到此问题。
  • 我一旦重新启动应用程序,就会看到最新的结果。
  • 当我执行查询时,iBATIS应该在MySQL客户端中运行,我执行查看iBATIS结果中缺少的新票证。
  • 当我使用Spring MVC和Spring Data JPA模拟一个简单的票证列表时,我执行查看新票证。

我也试图用iBATIS排除某种奇怪的交易状态,但似乎并没有在这里使用任何交易。

我错过了什么?还有什么我应该试图解决这个问题吗?或者,我是否应该优先使用Spring Data JPA替换iBATIS层,这似乎不受此问题的影响?

更新

我现在已经通过git bisect进行了很多我最近的更改,并且我已经将其缩小到引入Spring org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter的更改。

因此,似乎某些交易的生存时间比应有的长。我将添加更多日志记录以查看是否可以确认这一点,然后寻找避免使用该过滤器的方法。

2 个答案:

答案 0 :(得分:0)

如果您正在执行select,insert,请选择相同的SqlSession, 然后SqlSession缓存导致此问题。你需要 在insert:sqlSession.clearCache()。

之后手动清除缓存

答案 1 :(得分:0)

所以,似乎最终发生了一系列事情:

  1. 我的大部分代码都未明确使用交易。
  2. 我在某些时候更改为使用Tomcat's JDBC Connection Pool,当连接返回到池时,默认情况下不会重置autocommit。我希望我的旧的基于DBCP的东西可以隐含地做到这一点。
  3. OpenEntityManagerInViewFilter的引入可能导致SET autocommit=0在某个时刻被调用,如果没有任何更改,则之后没有相应的SET autocommit=1
  4. 偶然,或者某些设计,将新记录插入数据库然后立即检索并显示的代码似乎与显示我的记录列表的代码不同Connection。 / LI>
  5. REPEATABLE-READ的默认MySQL事务隔离级别意味着我的列表显示旧结果。
  6. 我发现的修复程序,目前在我的测试中似乎有效,是将这些defaultAutoCommitjdbcInterceptors属性添加到我的连接池配置中:

    <Resource name="jdbc/DB" auth="Container" type="javax.sql.DataSource"
        factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
        ...
        defaultAutoCommit="true" jdbcInterceptors="ConnectionState;StatementFinalizer" />