Как мне сделать мои pojos транзакционными? - PullRequest
3 голосов
/ 22 сентября 2009

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

Теперь, есть ли способ сделать мои pojos в памяти транзакционными на том же уровне, что и транзакции hibernate / spring? У меня есть сервисные вызовы, состоящие из 30 классов, и я никогда не знаю, где произойдет коммит. Какие у меня варианты?

Ответы [ 2 ]

2 голосов
/ 22 сентября 2009

Если я хорошо понимаю вашу потребность, вы спрашиваете что-то деликатное, в некоторых контекстах. Позвольте мне попробовать пример , чтобы проверить, правильно ли я понимаю :

  1. Поток T1 читает pojo P в кеш, получает версию P1.
  2. Поток T2 читает pojo P в кеш, получает версию P1.
  3. Поток T2 начинает транзакцию, читает то же pojo, изменяет значение, которое создает версию P2.
  4. Поток T1 читает pojo P в кеш, все еще получает версию P1. Для этого требуется, чтобы для пункта 3 T2 получил копию P2 версии P1, а не тот же объект.
  5. Поток T2 сохраняет P, ничего не меняется ни для T1, ни для T2, у них разные версии.
  6. Поток T2 закрывает транзакцию:
    а. в случае отката T2 будет использовать P1, как и T1.
    б. если зафиксировать, T2 продолжит использовать P2. Но теперь T1 также должен использовать P2.

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

Во-первых, Вам нужно убедиться, что вы действительно хотите что-то подобное!


Если ты действительно этого хочешь ..

Я предлагаю использовать технический код (AOP, ThreadLocal), чтобы скрыть эту сложную сложность от вашего функционального кода .

  • Вероятно, что ваш коммит / откат уже сделан через AOP, поэтому с этим проблем не должно быть.

  • Чтобы скрыть получение экземпляров P (иногда экземпляр в сохраненном кэше, иногда копию): используйте класс с именем Store для хранения значений в кэше, используйте переменную ThreadLocal типа Store. Я бы использовал переменную ThreadLocal для вашего текущего потока:

    • Экземпляр Store может быть изменен только в вашем транзакционном коде AOP, но не в вашем функциональном коде
    • Ваш функциональный код использует текущий экземпляр ThreadLocal для манипулирования объектами (сохранение и т. Д.) *
    • когда вне транзакции , экземпляр ThreadLocal является кэшированным, назовем его CACHE.
    • ввод транзакции устанавливает другой экземпляр ThreadLocal для текущего потока; этот класс является подклассом Store, который будет возвращать копии объектов кэшей, когда вы их запрашиваете; класс также запомнит, если некоторые из них сохранены (поэтому вам нужно сохранить их с помощью этого специального API или уведомить об этом в своем обычном API сохранения)
    • откат транзакция отбрасывает экземпляр ThreadLocal, переустанавливая экземпляр CACHED для текущего потока
    • принятие транзакция будет принимать все запомненные операции базы данных в экземпляре ThreadLocal, применять это для изменения экземпляра CACHED и переустанавливать экземпляр CACHED для текущего потока
1 голос
/ 22 сентября 2009

Не соответствует ли использование кэша 2-го уровня Hibernate вашим требованиям? Поставщик JBoss Cache является как распределенным, так и транзакционным.

Если это не сработает для вас, вам придется объяснить, почему и чего вы действительно пытаетесь достичь, чтобы получить значимые ответы.

...