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

pio*_*oto 8 java mysql spring caching ibatis

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

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

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

我试图排除的事情:

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

我也试图用iBATIS排除某种奇怪的事务状态,但似乎根本没有在这里使用任何事务.

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

UPDATE

我现在已经经历了很多我最近的变化git bisect,并且我已经将它缩小到引入Spring的变化org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.

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

pio*_*oto 0

所以,似乎这里发生了一些事情的组合:

  1. 我的大部分代码都没有明确使用事务。
  2. 我曾在某个时候更改为使用Tomcat 的 JDBC 连接池autocommit,当连接返回到池时,默认情况下它不会重置。不过,我希望我的旧的基于 DBCP 的东西隐式地做到了这一点。
  3. 的引入OpenEntityManagerInViewFilter可能会导致 aSET autocommit=0在某个时刻被调用,SET autocommit=1如果没有任何改变的话,之后就没有相应的调用。
  4. 偶然,或者可能是某种设计,将新记录插入数据库然后立即检索并显示它的代码似乎与显示Connection记录列表的代码不同。
  5. 默认的 MySQL 事务隔离级别REPEATABLE-READ意味着我的列表显示的是旧结果。

我发现的修复方法(到目前为止在我的测试中似乎有效)是将这些defaultAutoCommitjdbcInterceptors属性添加到我的连接池配置中:

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