I think your idea to workaround the fact that TransactionSynchronizationManager must play with single threaded transaction is interesting but probably dangerous.
In the TransactionSynchronizationManager the transactionnal resources are stored in a ThreadLocal Map where the key is the resource factory and I'm wondering what will append when you will execute this workaround with multiple threads using the same resource factory - it probably don't apply in your case since you have 3 datasource -. (At first sight I would say that one of your transactionnal resource will be replaced by another one, but maybe I'm missing something...).
Anyway, I think you can try to use the javax.transaction.TransactionManager.resume() to achieve what you are trying to do.
The idea is to use the JTA api directly and so by-passing single-thread Spring transaction support.
Here is some code to illustrate what I have in mind:
@Autowired
JtaTransactionManager txManager; //from Spring
javax.transaction.TransactionManager jtaTransactionManager;
public void parallelInserts() {
jtaTransactionManager = txManager.getTransactionManager(); //we are getting the underlying implementation
jtaTransactionManager.begin();
final Transaction jtaTransaction = jtaTransactionManager.getTransaction();
try {
Thread t1 = new Thread(){
@Override
public void run() {
try {
jtaTransactionManager.resume(jtaTransaction);
//... do the insert
} catch (InvalidTransactionException e) {
try {
jtaTransaction.setRollbackOnly();
} catch (SystemException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} catch (SystemException e) {
e.printStackTrace();
}
}
};
t1.start();
//same with t2 and t3
} catch (Exception ex) {
jtaTransactionManager.setRollbackOnly();
throw ex;
}
//join threads and commit
jtaTransactionManager.commit();
}
I think this solution may work (I must say that I didn't try myself). The only limitation that I see now is that you cannot re-use the threads because there is no counter-part to the resume() call and the second time you will call resume() you will probably have an IllegalStateException.