2016-09-29 3 views
0

У меня есть проект Hibernate с лицом, имеющей аналогичное отношением к следующему:Пинающе событие после того, как несколько объектов обновляются в Hibernate транзакции

Car { 
    String name; 
    Engine engine; 
} 

Engine { 
    String name; 
} 

У нас есть внешняя система (веб-службы, черный ящик), который должна быть обновлена ​​с изменениями, внесенными в указанных выше лиц, однако, внешняя система не делает различий между Car и Engine:

RemoteCar { 
    String name; 
    String engineName; 
} 

процесс синхронизации включает в себя получение экземпляра RemoteCar из удаленной системы, обновив значения, измененные с Car и Engine, а затем отправив запрос на обновление.

Я пытаюсь использовать PostUpdateEventListener с requiresPostCommitHanding возвращения true стартует событие приложения для обновления внешней системы, но если оба «имя s и Engine» Car имя s обновляются в одной и той же операции, я получаю два события, начиная с двух синхронизаций с внешней системой.

Есть ли способ гарантировать, что я получаю только те события, которые мне нужны? К сожалению, некоторые обновления до Engine выполняются напрямую (EngineDao.get(1).setName()), что означает, что Car никогда не задействован - я могу легко выполнить свой путь обратно в дерево, чтобы получить свой экземпляр Car, но я не вижу, как определить, обновляется ли до Engine является частью большого обновления Car или автономного обновления Engine.

ответ

1

Что я хотел бы предложить не синхронизировать с удаленной системой в каждом обратном вызове слушателя, потому что для случаев, о которых вы упомянули, это становится потенциальным узким местом ввода-вывода. Вместо этого я бы предложил поддерживать кеш-транзакцию и реплицироваться один раз.

PostUpdateEventListener Когда пожары, сделать что-то вроде следующего:

  1. Проверьте, если текущая транзакция имеет кэш. Если это не так, создайте кэш и зарегистрируйте перед вызовом транзакции commit (подробнее см. Ниже).
  2. Для каждого события обновления проверьте кеш, чтобы узнать, уже выбран ли соответствующий RemoteCar. Если это так, просто обновите кеш соответственно. Если он не находится в кеше, извлеките его из удаленной системы и обновите экземпляр кеша.

Во время фазы совершения транзакции завершается обратный вызов транзакции до совершения транзакции, который будет итерировать кешированные экземпляры, и в зависимости от вашего API может отправить массовое обновление (1 вызов ввода-вывода) в удаленную систему обновить все измененные экземпляры RemoteCar.

Это позволит использовать ваш случай, когда 2 обновления позволяют синхронизировать две точки синхронизации, чтобы сводиться к одной удаленной выборке, 2 локальным обновлениям и 1 обновлению репликации обратно во внешнюю систему.

+0

Спасибо за это. Как вы будете управлять своим кешем? Могу ли я использовать карту со значением PostUpdateEvent.getSession(). GetTransaction() как ключ в IdentityHashMap? (с правильной синхронизацией) – Rich

+0

Да, это именно то, что я делаю при управлении кешем процесса аудита, связанным с сеансом спящего режима в Envers. – Naros