we have this code where the same service
method will call different daos
each using a different datasource
(and different JdbcTemplate
s). We would like to use @Transactional
annotation, but as far as I know, this annotation is always linked to a specific TransactionManager
(and thus, to a specific DataSource
).
So, my question is, is there a way to choose dynamically which DataSource
(or TransactionManager
) using when calling a @Transactional
method so I can reuse that method to attack different databases?
The @Transactional
annotation doesn't allow dynamic evaluation of the value
attribute which selects the TransactionManager
(possibly by design, at least it doesn't look like it's going to change any time soon). So you can't have something like @Transactional("#{@getTxManager}")
which would resolve the tx manager at call time.
In simple cases you might be able to get away with the following, but it would only be worth considering when for example you have a primary DS, and a secondary DS that's used only in some cases. Otherwise you'd be peppering the code that selects between calling foo/bar
all around, and that wouldn't look clean at all
// TX boundary on the "top" abstraction layer
@Transactional("foo")
public void foo() {
doWork();
}
@Transactional("bar")
public void bar() {
doWork();
}
private void doWork() {
// Work done here, no concern for tx management
}
For more complex cases like multitenancy, AbstractRoutingDataSource is an easy and robust choice if you haven't considered it yet. Although depending on how much switching you need, it may require tweaking or be even unsuitable.
Finally, you might be able to create your own annotation that does choose the DS dynamically (although I don't guarantee it), but that would be the riskiest approach for possible very little gains.