Я получаю это исключение в контроллере веб-приложения на основе структуры spring, используя спящий режим. Я пробовал много способов противостоять этому, но не смог его решить.
В методе контроллера handleRequestInternal
в базу данных поступают вызовы в основном для "чтения", если только это не действие отправки.
Я использовал сеанс spring, но перешел в getHibernateTemplate()
, и проблема все еще остается.
в основном, это второй вызов базы данных вызывает это исключение. То есть:
1) getEquipmentsByNumber(number)
{сначала оборудование извлекается из БД на основе "числа", которое имеет список свойств, а каждое свойство имеет список значений. Я просматриваю эти значения (примитивные объекты Strings) для чтения в переменные)
2) getMaterialById(id)
{извлекает материалы на основе id}
Я понимаю, что второй вызов, скорее всего, делает сеанс "флешем", но я только "читаю" объекты, то почему второй вызов выдает исключение состояния устаревшего объекта в свойстве "Оборудование", если есть ничего не изменилось?
Я не могу очистить кеш после вызова, поскольку он вызывает LazyExceptions для объектов, которые я передаю в представление.
Я прочитал: https://forums.hibernate.org/viewtopic.php?f=1&t=996355&start=0 но не смог решить проблему на основе предложенных предложений.
Как я могу решить эту проблему? Любые идеи и мысли оценены.
UPDATE:
То, что я только что проверил, это то, что в функции getEquipmentsByNumber()
после чтения переменных из списка свойств я делаю это: getHibernateTemplate().flush();
, и теперь исключение находится в этой строке, а не в вызове для извлечения материала (т.е. getMaterialById(id)
).
UPDATE: Перед явным вызовом flush я удаляю объект из кеша сеанса, чтобы в кэше не осталось ничего устаревшего объекта.
getHibernateTemplate().evict(equipment);
getHibernateTemplate().flush();
ОК, так что теперь проблема переместилась на следующую выборку из БД после того, как я это сделал. Полагаю, мне нужно пометить методы как синхронизированные и вытеснить объекты, как только я закончу читать их содержимое! это звучит не очень хорошо.
UPDATE:
Сделал метод handleRequestInternal
"синхронизированным". Ошибка исчезла. Конечно, не лучшее решение, но что делать!
Протестировано в handleRequestInternal
, чтобы закрыть текущий сеанс и открыть новый. Но это может привести к тому, что другие части приложения не будут работать должным образом. Пытался использовать ThreadLocal
, который тоже не работал.