Ehcache не работает в кластерном приложении
В моем приложении есть монолитное приложение, которое предоставляется Spring Ehcache. Оно работает правильно. Важно знать, что конфигурация кэша выполняется при сервисном методе, и отложенная загрузка выполняется для всех объектов, запрашиваемых из DB. Например:
@Transactional
@Override
@Caching(evict = { @CacheEvict(value = "schoolCache", key = "#school.id")})
public Integer save(School school) {
// Code here
}
Ясно, что то, что сохраняется в Ehcache, является ленивым экземпляром школы. На уровне контроллера есть ModelMapper для обмена данными между Model и ViewModel следующим образом:
@RequestMapping(value = "/load/{Id}", method = RequestMethod.GET)
@ResponseBody
public SchoolViewModel load(@PathVariable Integer Id) {
SchoolViewModel schoolViewModel = ModelMapper.map(schoolService.loadByEntityId(Id), SchoolViewModel.class);
return schoolViewModel;
}
Если SchoolViewModel имеет атрибут объекта, который находится в школе, выбирается из БД на контроллере с помощью ModelMapper. Поэтому я кластеризовал приложение и настроил Ehcache для Redis.
В чем проблема? В начале, когда запрос запроса от SchoolService, этот запрос службы из БД и, поскольку сеанс hibernate был открыт,ModelMapper успешно отображает Model в ViewModel. Во второй раз метод службы, который вызывается с идентификатором id, идентичным идентификатору сначала время получения школьного объекта от Redis, и нет сеанса Hiberante,ModelMapper, который хочет отобразить атрибут объекта, который находится в школе, получает исключение. Исключение выглядит так:
Вызвано: org.hibernate.LazyInitializationException: не удалось инициализировать прокси-сервер - нет сеанса в org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) в org.hibernate.proxy.AbstractLazyInitleizer.Lite.jpg). в org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
Так как мне это сделать? Как мне лучше всего помочь? большое спасибо
1 ответ
Как я объяснил в моей книге, вам нужно инициализировать все ассоциации, которые вам понадобятся в методе обслуживания:
schoolService.loadByEntityId(Id), SchoolViewModel.class)
Итак, у вас есть несколько вариантов:
- Вы можете использовать JOIN FETCH с запросом JPQL.
- Ты можешь использовать
Hibernate.initialize(proxy)
или жеHibernate.unproxy(proxy)
, - Вы можете просто перемещаться по ленивым ассоциациям.
- Вы можете использовать проекцию DTO, и вы никогда не столкнетесь с
LazyInitializationException
,