Шаблон управления транзакциями на уровне объекта - PullRequest
5 голосов
/ 16 января 2009

Я пытаюсь найти лучший способ обработки транзакций на уровне объекта (не на уровне базы данных). Краткий пример: 4 объекта A, B, C и D. A запускает транзакцию и вызывает методы в B и C. В то время как эта транзакция C также вызывает D. Вызываемые методы не всегда должны участвовать в этой транзакции, но можно назвать и самостоятельно. Существуют ли какие-либо шаблоны для управления транзакциями на уровне объекта?

Я ничего не нашел, поэтому придумал: используйте TransactionContext, где можно зарегистрировать TransactionListeners. Если транзакция запускается с использованием TransactionContext, то она внедрит запущенную транзакцию в каждого из зарегистрированных слушателей, которые, в свою очередь, будут использовать запущенную транзакцию или в противном случае запустят ее самостоятельно, если это необходимо. Таким образом, я могу свободно решать, хочу ли я участвовать в моей транзакции или нет.

Проблема возникает при наличии цепочек вызова объектов, как описано выше. При запуске транзакции я просто знаю, что B и C должны участвовать в транзакции, поэтому я добавляю их в TransactionContext. Но как насчет D? Я действительно не хочу передавать TransactionContext B и C.

Буду признателен за некоторую информацию о моем подходе, а также за некоторые указания на проверенные шаблоны (даже лучше).

Ответы [ 4 ]

2 голосов
/ 16 января 2009

«Я действительно не хочу передавать TransactionContext блокам B и C».

Почему бы и нет? Они участвуют и делегируют другие объекты.

Или

  • Каждый должен зарегистрироваться. Что означает, что вы должны делегировать регистрацию. A знает, что он передает B и C. Каждый из которых может (или не может) иметь дополнительных делегатов для регистрации. Это относительно просто реализовать с помощью метода RegisterYourselfAndYourDelegatees.

  • Откажитесь от шаблона проектирования Слушателя. Создайте контекст транзакции и передайте его. Это заменяет регистрацию и внедрение более простым дизайном. Однако вам нужно иметь два подкласса Context - реальный Context и заглушки Context, которые ничего не делают и используются вне контекста транзакции.

    Это делает ваши определения функций немного более сложными. Для Java вы можете использовать перегруженное именование, чтобы иметь две функции метода с разными сигнатурами.

    Для Python это не проблема; контекст является необязательным аргументом.

1 голос
/ 16 января 2009

Платформа Spring (изначально для Java, но сейчас есть и версия .Net) может это сделать. Методы помечены как:

  • Требуется транзакция (начинается, если ее еще нет);
  • Требуется новая транзакция (всегда создает новую);
  • и т.д.

Обычно это делается с аннотациями. Звучит так же, как вы описываете.

Оформить Управление транзакциями Spring .

0 голосов
/ 16 января 2009

Настоятельно рекомендуем эту статью Андрея Александреску и Петру Марджиняна, которая представляет ScopeGuard patten. Это элегантное и очень надежное решение для управления транзакциями, особенно при наличии исключений.

Применимая к проблеме, которую вы пытаетесь решить, ScopeGuard позволит вам определить объем вашей транзакции и легко (то есть автоматически) решить ее для вас, независимо от того, включает ли транзакция методы A, B, C, D или вызов отдельных методов. .

0 голосов
/ 16 января 2009

Я бы предложил: Prevayler

Prevayler is an object persistence library for Java. It is an implementation of the
System Prevalence architectural style, in which data is kept hot in Memory with
changes journaled for system recovery.

Prevayler ' s architecture is illustrated in the diagram shown there. Prevayler [1]
serves as a transactional barrier for the business objects [2] of your application,
held in Memory. You encapsulate all modifications of your business objects into
instances of the Transaction interface [3], much like a " command " pattern
(though different from a command in some details of the pattern). Whenever 
you ask Prevayler to execute a transaction on your business objects [4], Prevayler
first writes the transaction object to a journal [5] so that data is not lost if your
system crashes. Prevayler can also write a snapshot of your entire business object
graph [6] as often as you wish. Prevayler uses the latest snapshot together with
the journals to automatically recover your business objects from disk [7] on
application startup by restoring the snapshot and then re-executing every
transaction that was originally executed after that snapshot was taken.

Конечно, вы можете отключить постоянное хранилище и использовать только хранилище в памяти.

...