Just for studying purposes, I developed a single DAO class, to persist data on different databases using JPA.
In my scenario, my DAO class is going to serve two different user groups; each user group has a specific database associated with, so, for example, GroupA will persist its data on a MySql instance on ServerA, while GroupB will persist its data on a MySql instance on ServerB. I don't want to deploy two different copies of my Spring Application, so that I need a way to dinamycally choose which database the program must work with. Choose which database to use, in JPA, is more or less the same to choose which EntityManager use at each service request.
This is my Spring configuration: I defined two different datasource and two different EntityManagers:
I defined a very simple EntityManagerLocator to lookup for a given EntityManager:
I defined a single, simple entity, named Person, meant to be the same on both databases:
The corrisponding Dao service has been named, without much imagination, PersonDao :
In PersonDAO is where my perplexities lie. First, normally one should see in Spring examples methods like savePerson to be annotated with @Transactional. The problem is that to be able to mark with @Transactional a method, one should define a PlatformTransactionManager, but as far as I know there's no way to use a single TransactionManager for more EntityManagers: you can bind a TransactionManager to a single EntityManager.
In my sample code, I select the wanted EM using EntityManagerLocator, then I start and then I commit a manual transaction. Curiously, in this case I don't need to define a PlatformTransactionManager.
I wonder if above code may be considerated a good practice in Spring - which I'm a newbie of - or it's completely wrong (even if it actually works, this doesn't imply it's a good code).
What do you think about ? Please advice.
At the very end, and after quite a lot of efforts, I managed it
I needed to introduce a JTA provider, and let it manage transactions; this way, I was able to use @Transactional annotation on my PersonDAO class.
First, I needed to change LocalContainerEntityManagerFactoryBean injection method:
Second, I defined an helper class to wrap JTA provider implementation (I used Narayana from JBoss, by the way) :
Last, I need to inject a PlatformTransactionManager which, in turn, uses JTAPlatform helper class defined above:
Maybe there are cleverer solutions, as far as I'm concerned I'm really satisfied
Spring documentation on this topic isn't so clear... at least for me.