How do I get the connection inside of a Spring transaction?
I assume you are using Plain Jdbc, you need to do is :
BaseDao {
@Autowired
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public Connection getConnection() {
// ....use dataSource to create connection
return DataSourceUtils.getConnection(dataSource);
}
}
FooDao extends BaseDao {
// your foo() method
void foo() {
Connection conn = getConnection();
//....
}
}
(completely rewritten based on comment thread; not sure why my original answer was focused on Hibernate, other than that's what I'm working with right now)
The transaction manager is completely orthogonal to data sources. Some transaction managers interact directly with data sources, some interact through an intermediate layer (eg, Hibernate), and some interact through services provided by the container (eg, JTA).
When you mark a method as @Transactional
, all that means is that Spring will generate a proxy when it loads your bean, and that proxy will be handed to any other class that wants to use your bean. When the proxy's method is invoked, it (the proxy) asks the transaction manager to either give it an outstanding transaction or create a new one. Then it calls your actual bean method. When your bean method returns, the proxy interacts with the transaction manager again, to either say "I can commit" or "I must rollback". There are twists to this process; for example, a transactional method can call another transactional method and share the same transaction.
While the transaction manager interacts with the DataSource
, it does not own the DataSource
. You cannot ask the transaction manager to give you a connection. Instead, you must inject a frame-specific object that will return connections (such as the Hibernate SessionFactory
). Alternatively, you can use the static transaction-aware utility classes, but these again are tied to a specific framework.
You can probably try DataSourceUtils.getConnection(dataSource)
, per the API it should return you the current connection for the datasource.
Update:
Based on your comments and the source code for org.springframework.transaction.support.TransactionSynchronizationManager
:
Like I said, the key to getting the connection is the datasource name, if this cannot be obtained, one way out by looking at the source code is to try this:
TransactionSynchronizationManager.getResourceMap()
will return a map of datasource to ConnectionHolder in the current thread, assuming that you have only 1 resource involved in transaction, you can probably do a map.values().get(0)
to get the first ConnectionHolder, from which you can get a connection by calling .getConnection()
So essentially calling the following:
TransactionSynchronizationManager.getResourceMap().values().get(0).getConnection()
There probably has to be better way though :-)