Почему iBATIS дает устаревшие результаты, даже если кэширование отключено?
У меня есть веб-приложение, которое я медленно мигрировал с iBATIS 2 на JPA с данными Spring.
По большей части дела идут хорошо, и я просто переношу DAO для одного объекта домена за раз. Тем не менее, проблема, которая была недавно доведена до моего сведения, заключается в том, что устаревшие списки результатов отображаются в некоторых частях сайта.
Например, у меня есть раздел "билет", который показывает список открытых билетов и позволяет просматривать определенные билеты на отдельных сайтах. страницы. Когда я создаю новый билет, я могу правильно просмотреть его на определенной странице. Однако в списке открытых билетов этот новый билет появится только через некоторое время.
Вещи, которые я пытался исключить:
- я вижу эту проблему даже в системе с отключенным кэшем запросов MySQL
- я вижу эту проблему, даже когда устанавливаю
cacheModelsEnabled="false"
в конфигурации iBATIS. - я вижу эту проблему даже тогда, когда я полностью удаляю элемент
<cacheModel>
и атрибутыcacheModel="x"
из моей sqlMap файл. - как только я перезапускаю приложение, я вижу последние результаты.
- Когда я выполняю запрос iBATIS должен быть запущен здесь в клиенте MySQL, я делаю вижу новый билет, который отсутствует в результатах iBATIS.
- Когда я издевался над простым списком билетов, используя Spring MVC и Spring Data JPA, я действительно вижу новый билет.
Я также пытался исключить какое-то странное состояние транзакции с iBATIS, но похоже, что нет транзакция здесь вообще используется.
Что я упускаю? Есть ли что-то еще, что я должен попытаться выяснить? Или, может быть, мне просто следует полностью заменить слой iBATIS на Spring Data JPA, который, похоже, не подвержен этой проблеме?
Обновить
Теперь я прошел через множество моих недавних изменений с git bisect
, и я сузил его до изменения, которое ввело весенние org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
.
Итак, казалось бы, какая-то транзакция живет дольше, чем следовало бы. Я добавлю больше журналов, чтобы проверить, могу ли я подтвердить это, а затем искать способ избежать использования этого фильтра.
2 ответа:
Если вы делаете select, insert, select в том же SqlSession, тогда кэш SqlSession вызывает эту проблему. Вам нужно будет очистите кэш вручную после вставки: sqlSession.команды clearcache().
Итак, похоже, что здесь произошло сочетание вещей:
Большая часть моего кода явно не использовала транзакции.
- я в какой-то момент изменил использование пула соединений JDBC Tomcat, который не сбрасывает
autocommit
по умолчанию, когда соединение возвращается в пул. Хотя я ожидаю, что мои старые материалы на основе DBCP делали это неявно.- введение
Случайно или, возможно, по какой-то задумке, код, который вставлял новую запись в базу данных, а затем немедленно извлекал и показывал ее, казалось, получал другойOpenEntityManagerInViewFilter
, возможно, вызвало вызовSET autocommit=0
в какой-то момент, без соответствующегоSET autocommit=1
позже, если ничего не изменилось.Connection
, чем код, который показывал мой список записей.- уровень изоляции транзакций MySQL по умолчанию
REPEATABLE-READ
означал, что мои списки показывали старые результаты.Исправление, которое я нашел, которое, кажется, работает в моем тестировании до сих пор, состоит в том, чтобы добавить эти
defaultAutoCommit
иjdbcInterceptors
атрибуты конфигурации моего пула соединений:<Resource name="jdbc/DB" auth="Container" type="javax.sql.DataSource" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" ... defaultAutoCommit="true" jdbcInterceptors="ConnectionState;StatementFinalizer" />