2009-01-16 14 views
5

Estoy tratando de encontrar la mejor manera de manejar transacciones a nivel de objeto (no a nivel de base de datos). Ejemplo corto: 4 objetos A, B, C y D. A inicia una transacción y llama a los métodos en B y C. Dentro de esta transacción, C también llama a D. Los métodos a los que se llama no deben participar siempre en esta transacción, pero también se pueden llamar por su cuenta. ¿Hay algún patrón para administrar las transacciones a nivel de objeto?Patrón de gestión de transacciones a nivel de objeto

Realmente no encontré algo, así que se me ocurrió esto: use un TransactionContext donde pueda registrar TransactionListeners. Si se inicia una transacción utilizando TransactionContext, inyectará la transacción en ejecución en cada uno de los oyentes registrados, que a su vez utilizará una transacción en ejecución o, si no, la iniciará por sí misma si es necesario. De esta manera soy bastante libre de decidir si quiero que un objeto participe en mi transacción o no.

El problema se produce cuando se tienen cadenas de llamadas de objetos como las de arriba. Al iniciar la transacción, sé que B y C deben participar en la transacción, así que los agrego al TransactionContext. ¿Pero qué hay de D? Realmente no quiero pasar el TransactionContext alrededor de B y C.

Agradecería algunas sugerencias sobre mi enfoque, así como algunos consejos sobre patrones comprobados (incluso mejores).

Respuesta

2

"Realmente no quiero pasar el TransactionContext alrededor de B y C."

¿Por qué no? Ellos participan y delegan a otros objetos.

De cualquier

  • Todo el mundo tiene que registrarse. Lo que significa que debe delegar el registro. A sabe que da la orden a B y C. Cada uno de los cuales puede (o no) tener delegados adicionales para registrarse. Esto es relativamente simple de implementar con un método "RegisterYourselfAndYourDelegatees".

  • Evite el patrón de diseño del Listener. Crea un contexto de transacción y pásalo. Esto reemplaza el registro y la inyección con un diseño un poco más simple. Sin embargo, deberá tener dos subclases de contexto: el Contexto real y un Contexto que no hace nada y que se usa fuera del contexto de una transacción.

    Esto hace que las definiciones de sus funciones sean un poco más complejas. Para Java, puede usar una denominación sobrecargada para tener dos funciones de método con diferentes firmas.

    Para Python, esto no es un problema; el contexto es un argumento opcional.

1

El Spring framework (inicialmente para Java pero también hay una versión de .Net ahora) puede hacerlo. Los métodos están marcados como:

  • Requiere una transacción (inicia una si ya no hay una);
  • Requiere una nueva transacción (crea una nueva siempre);
  • etc.

Esto normalmente se realiza con anotaciones. Suena exactamente como lo que describes.

Consulte Spring's transaction management.

+0

Sé que Spring y también el servidor de aplicaciones proporcionan esto, pero no quiero utilizar ninguno de ellos. Pero gracias por el puntero a Spring transactionmanagemenr. Voy a leer eso. – MicSim

+0

En Java es un patrón bastante estándar y muchas bibliotecas lo implementan. – Loki

+0

¿Por qué no quieres usar JTA o Spring? – Loki

0

me gustaría sugerir: 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. 

Por supuesto, se puede desactivar el almacenamiento persistente y utilizar sólo la tienda en-memoria.

0

Recomendamos encarecidamente this paper por Andrei Alexandrescu y Petru Marginean, que presenta ScopeGuard patten. Esta es una solución elegante y muy robusta para administrar transacciones específicamente en presencia de excepciones.

Aplicable al problema que está tratando de resolver ScopeGuard le permitirá definir el alcance de su transacción y gestionarla fácilmente (es decir, automáticamente) si la transacción implica métodos A, B, C, D o llamadas individuales métodos.

Cuestiones relacionadas