Как отделить модуль, который прослушивает событие гибернации, от самих сущностей?
У меня есть многоуровневое веб-приложение, управляемое spring-jpa-hibernate, и я сейчас пытаюсь интегрировать asticsearch (поисковик).
Что я хочу сделать, так это перехватить все события post Insert/postUpdate и отправить эти объекты в asticsearch, чтобы он переиндексировал их.
Проблема, с которой я сталкиваюсь, заключается в том, что мой проект "dal-entity " будет иметь зависимость времени выполнения от "search-indexer", а "search-indexer" будет зависеть от компиляции "dal-entity ", так как он должен делать разные вещи для разных сущностей.
Я думал о том, чтобы иметь "поисковый индексатор" как часть DAL (поскольку можно утверждать, что он выполняет операции с данными), но даже в этом случае он должен быть частью раздела DAO.
Я думаю, что мой вопрос можно перефразировать следующим образом: как я могу иметь логику в приемнике событий гибернации, который не может быть инкапсулирован исключительно в проекте лица (поскольку это не входит в его обязанности).
Обновить
Причина, по которой проект dal-entity зависит от индексатора, заключается в том, что мне нужно настроить прослушиватель в файле конфигурации Spring, который отвечает за контекст jpa (который явно находится в dal-entity).
Зависимость - это не область времени компиляции, а область времени выполнения (поскольку во время выполнения этому прослушивателю потребуется контекст гибернации).
2 ответа
Ответ - Интерфейсы.
Вместо того, чтобы зависеть от различных классов напрямую (в любом направлении), вы можете вместо этого зависеть от интерфейсов, которые предоставляют необходимые вам возможности. Таким образом, вы напрямую независите от классов, но вместо этого зависите от интерфейса, и вы можете иметь интерфейсы, требуемые для "dal-entity", например, жить в том же пакете, что и dal-entity, и индексатор просто реализует этот интерфейс.
Это не полностью удаляет зависимость, но дает вам гораздо менее тесную связь и делает ваше приложение более гибким.
Если вы все еще беспокоитесь о слишком тесной взаимосвязи вещей или действительно не хотите, чтобы эти две части были циклически зависимыми, я бы посоветовал вам переосмыслить дизайн вашего приложения. Если вы зададите здесь другой вопрос о SO с более подробной информацией о некотором вашем коде и о том, как он может быть лучше структурирован, вы, вероятно, получите хороший совет о том, как улучшить дизайн.
Hibernate поддерживает PostUpdateEventListener и PostInsertEventListener.
Вот хороший пример, который может подойти вашему делу
Основная концепция заключается в возможности определить, когда ваша сущность была изменена, и действовать после нее, как показано здесь.
public class ElasticSearchListener implements PostUpdateEventListener {
@Override
public void onPostUpdate(PostUpdateEvent event) {
if (event.getEntity() instanceof ElasticSearchEntity ) {
callSearchIndexerService(event.getEntity());
Or
InjectedClass.act(event.getEntity());
Or
callWebService(InjectedClassUtility.modifyData(event.getEntity()));
........
}
}
редактировать
Вы можете рассмотреть возможность внедрения класса, который вы хотите изолировать от проекта (который содержит логику), с помощью Spring.
Другим вариантом может быть вызов внешнего веб-сервиса, который не зависит от вашего кода. передавая ему либо исходный объект проекта, либо объект, модифицированный утилитой, чтобы соответствовать asticsearch.