Transaction like programming in Java
I want to achieve transaction like functionality in java. I want to do `n' operations like- one operation to update database, one to insert in a queue, one operation to update another data structure etc., All these operations should behave as one tr开发者_运维百科ansaction, i.e., if it succeeds, all the operations should be successfully done, otherwise, if one fails, everything should fail. One of the brute force approach is to write try-catch blocks and revert all the operations in catch blocks. Any pointers in solving these type of problems? Is there any pattern or library for achieving this?
Nope, you want JTA.
The brute force way would be to use JDBC and manage commit and rollback yourself.
The easiest way of all would be to use Spring or EJB3.1 and declarative transactions.
I think the pattern you are looking for is Command.
Transactional behavior
Similar to undo, a database engine or software installer may keep a list of operations that have been or will be performed. Should one of them fail, all others can be reverted or discarded (usually called rollback). For example, if two database tables which refer to each other must be updated, and the second update fails, the transaction can be rolled back, so that the first table does not now contain an invalid reference.
I've done this with a combination of the Command and Composite Design Patterns. The Transaction class is abstract and contains begin() & rollback() methods. The CompositeTransaction is derived from Transaction and stores a list of Transaction objects. For each group of operations that need to be treated as an atomic transaction, create a subclass of the CompositeTransaction and add your Transaction classes to this. see the CompositeTransaction here:
http://hillside.net/plop/plop99/proceedings/grand/plop_99_transaction_patterns.pdf
a visitor pattern works well. also, you will need to make sure you issue the commit at the right time. if you wait until the set of inserts/updates in complete, then issue commit, your described behavior should be automatic.
sounds like maybe you need a little refactor of your sql staement class to make sure you can issue some statements without the implied commit.
This is just a logic about how can you achieve this.
Write a method for each transaction as you want. Probably it would have all its resources. Like jdbc transaction will have Connection object and query as a requirement, file operation if any will have file path, and so on.
So for 5 transaction, there will be 5 different methods. You can achieve it in a single method as well but this is just for simplicity.
e.g.
method1(...) throws Exception {
...
// if any exception occurs then control will be passed to caller of this
// method
throw new Exception("1"); // write method number
}
Then write a method as (following is just a template):
public long/void transaction(...) throws Exception
{
try {
this.method1(...);
this.method2(...);
this.method3(...);
} catch (Exception e) {
// get that number in a exception message
// and try to undo all operations numbers less than above number.
// e.g. if that transaction method is any database transaction then
// try to rollback it.
// if it is creation of any file say log file then delete it
// now further logic depends on what the transaction was and how to
// undo it...
}
}
Thanks.
精彩评论