1
0
mirror of synced 2024-12-15 07:36:03 +03:00

Added documentation about control abstractions for transaction handling.

This commit is contained in:
Roman S. Borschel 2010-05-13 13:06:16 +02:00
parent 0799a5b5e9
commit 84c1d34028
2 changed files with 34 additions and 4 deletions

View File

@ -198,11 +198,21 @@ Transaction demarcation with the Doctrine DBAL looks as follows:
try{
// do stuff
$conn->commit();
} catch(\Exception $e) {
} catch(Exception $e) {
$conn->rollback();
//handle or rethrow
throw $e;
}
Alternatively, the control abstraction `Connection#transactional($func)` can be used to make
the code more concise and to make sure you never forget to rollback the transaction in the case
of an exception. The following code snippet is functionally equivalent to the previous one:
[php]
$conn->transactional(function($conn) {
// do stuff
});
The `Doctrine\DBAL\Connection` also has methods control the transaction isolation level as supported by the underlying database.
`Connection#setTransactionIsolation($level)` and Connection#getTransactionIsolation() can be used for that purpose.
The possible isolation levels are represented by the following constants:

View File

@ -51,15 +51,35 @@ Explicit transaction demarcation is required when you want to include custom DBA
or when you want to make use of some methods of the `EntityManager` API that require an active transaction.
Such methods will throw a `TransactionRequiredException` to inform you of that requirement.
A more convenient alternative for explicit transaction demarcation is the use of provided control
abstractions in the form of `Connection#transactional($func)` and `EntityManager#transactional($func)`.
When used, these control abstractions ensure that you never forget to rollback the transaction or
close the `EntityManager`, apart from the obvious code reduction. An example that is functionally
equivalent to the previously shown code looks as follows:
++ Exception Handling
[php]
// $em instanceof EntityManager
$em->transactional(function($em) {
//... do some work
$user = new User;
$user->setName('George');
$em->persist($user);
});
The difference between `Connection#transactional($func)` and `EntityManager#transactional($func)` is
that the latter abstraction flushes the `EntityManager` prior to transaction commit and also closes
the `EntityManager` properly when an exception occurs (in addition to rolling back the transaction).
+++ Exception Handling
When using implicit transaction demarcation and an exception occurs during `EntityManager#flush()`, the transaction
is automatically rolled back and the `EntityManager` closed.
When using explicit transaction demarcation and an exception occurs, the transaction should be rolled back immediately
and the `EntityManager` closed by invoking `EntityManager#close()` and subsequently discarded, as demonstrated in
the example above. Note that when catching `Exception` you should generally rethrow the exception. If you intend to
the example above. This can be handled elegantly by the control abstractions shown earlier.
Note that when catching `Exception` you should generally rethrow the exception. If you intend to
recover from some exceptions, catch them explicitly in earlier catch blocks (but do not forget to rollback the
transaction and close the `EntityManager` there as well). All other best practices of exception handling apply
similarly (i.e. either log or rethrow, not both, etc.).