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