I'm getting lost, @deeky666 ; how is an atomic operation, independent from the current transaction, possible with the concept of transaction propagation you introduced earlier?

Moving forward, I think we can safely leave the transaction propagation discussion for later, as it seems that it does not belong to the `createTransaction()` method call anyway, so it could potentially be introduced even after this PR is merged, with little trouble, what do you think?

In that case, we're left to deal with *transaction naming* and *read-only transactions* for now; as far as I can see from the Oracle and SQL Server docs, these concepts must be part of the statement that begins the transaction itself; this excludes the possibility to set them by calling methods on the `Transaction` object - because the transaction is already started at this point -, and forces us to include these concepts in the `createTransaction()` method call itself. So this really limits the choices. Amongst them, I can see:

- **The semantic way**: as you suggested, we introduce a TransactionDefinition object, and any option must be passed by creating a TransactionDefinition object:  
`public function createTransaction(TransactionDefinition $definition = null)`  
TBH I personally find it quite cumbersome to have to create such an object every time you just want to set the isolation level.
- **The pragmatic way**: we just add parameters with default values every time we want to introduce a new option to `createTransaction()`:  
`public function createTransaction($isolationLevel = 0, $readOnly = false, $name = null)`  
We can very well continue adding parameters to the function in the future, without breaking the API, as long as they have default values. I agree it's not very pretty, nor maintainable, though.
- **The hybrid way**: we put the potentially most useful (and currently only one supported) option as the first parameter to `createTransaction`, and allow an optional second parameter, a TransactionDefinition, to set more advanced options:  
`public function createTransaction($isolationLevel = 0, TransactionDefinition $definition = null)`

**OR** We choose a totally different route, and come back on the idea of having `createTransaction()` *create* the transaction object, but not *begin* the transaction. Then problem solved, we can have a future-proof API where any option is set on the Transaction object:

    $tx = $em->createTransaction();
    $tx->setIsolationLevel(Connection::TRANSACTION_REPEATABLE_READ);
    $tx->setReadOnly(true);
    $tx->begin();

Now *this* problem is solved, but new questions are raised: what happens if you begin() a nested transaction before its parent? What if you forget to call begin()? The simple, neat call to `createTransaction()` has now become:

    $em->createTransaction()->begin();

and makes it easy to make the mistake to forget to begin the transaction (even though I think it could be easily spotted by throwing an exception when trying to commit() or rollback() a non-begun transaction).

Whoa, that's a lot of options, all with pros and cons. What do you guys think about all of this?