Reputation: 1665
I'm a newbie with Java and I need to create a console application that is going to connect with 4 databases (access, vfp, mysql and sqlserver).
I started with hibernate.cfg.xml files and managed to configure them, one for each database. Then I realized that jpa was a better solution. So I changed all my hibernate files to a persistence.xml file with 4 persistence-unit.
The databases are working well, but to use them I have to create a lot of code. This is an example:
EntityManagerFactory dbPersistence =
Persistence.createEntityManagerFactory("oneOfMyDatabases");
EntityManager em = dbPersistence.createEntityManager();
Query query = em.createQuery("from ProductEntity").setMaxResults(10);
for (Object o : query.getResultList()) {
ProductEntity c = (ProductEntity) o;
System.out.println("Product " + c.getName());
}
cgPersistence.close();
I need to update one of the databases with data from the other databases.
It's a pain to create all the code like this, so I was thinking about creating repositories but I can't see how to create them with different entityManagers for each database.
I tried to inject the managers with google guice without success, but I couldn't handle how to close or where to close the persistence connection.
Finally, I've found Spring Data and it seems to be what I need, but I don't really understand how to use it.
I need some guide to get it working because I've read tons of tutorials and each of them appear to be different: · Can I use the same persistence.xml or do I need another configuration file? I've seen that Spring Data has jpa compatibility but I'm not sure how it works. · Is Spring Context the IOC Container of Spring Framework? Do I need it to work with Spring Data? · What else do I need?
Thank you in advance
Upvotes: 3
Views: 1024
Reputation: 154120
Each database is going to be represented by a different data source. For every data source you need a different session factory/entity manager factory.
If you want to save in more than one data source in a single transaction you then need XA transactions, therefore a Java EE or a stand-alone transaction manager, like Bitronix or Atomikos.
You have 4 different entity manager factories, you also need specific repositories for each of those:
<jpa:repositories base-package="your.company.project.repository.access" entity-manager-factory-ref="accessEntityManagerFactory"/>
<jpa:repositories base-package="your.company.project.repository.sqlserver" entity-manager-factory-ref="sqlserverEntityManagerFactory"/>
Then your application doesn't have to care which repository it uses.
The JpaTransactionManager requires one entityManagerFactory, but since you have 4 you may end up creating for of those, which I think it's undisirable.
It's better to switch to JTA instead:
<!-- 1. You define the Bitronix config ->
<bean id="btmConfig" factory-method="getConfiguration" class="bitronix.tm.TransactionManagerServices">
<property name="serverId" value="spring-btm"/>
<property name="warnAboutZeroResourceTransaction" value="true"/>
<property name="logPart1Filename" value="${btm.config.logpart1filename}"/>
<property name="logPart2Filename" value="${btm.config.logpart2filename}"/>
<property name="journal" value="${btm.config.journal:disk}"/>
</bean>
<!-- 2. You define all your data sources ->
<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init"
destroy-method="close">
<property name="className" value="${jdbc.driverClassName}"/>
<property name="uniqueName" value="dataSource"/>
<property name="minPoolSize" value="0"/>
<property name="maxPoolSize" value="5"/>
<property name="allowLocalTransactions" value="false"/>
<property name="driverProperties">
<props>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
<prop key="url">${jdbc.url}</prop>
</props>
</property>
</bean>
<!-- 3. For each data source you create a new persistenceUnitManager and you give its own specific persistence.xml ->
<bean id="persistenceUnitManager" depends-on="transactionManager"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"/>
<property name="defaultDataSource" ref="dataSource"/>
<property name="dataSourceLookup">
<bean class="org.springframework.jdbc.datasource.lookup.BeanFactoryDataSourceLookup"/>
</property>
</bean>
<!-- JpaDialect must be configured for transactionManager to make JPA and JDBC share transactions -->
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
<!-- 4. For each data source you create a new entityManagerFactory ->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
<!-- 5. You have only one JTA transaction manager ->
<bean id="jtaTransactionManager" factory-method="getTransactionManager"
class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig, dataSource"
destroy-method="shutdown"/>
<!-- 6. You have only one Spring transaction manager abstraction layer ->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="jtaTransactionManager"/>
<property name="userTransaction" ref="jtaTransactionManager"/>
</bean>
If this proves too much work for your current problem, you can give a try to having 4 JPA transaction managers and see how it works.
Upvotes: 3
Reputation: 532
If your schema is same across all the databases, then the best approach is to use hibernate,because hibernate provides portability between multiple databases. once you create the hbm files and pojo classes, the only thing you need to change is the dialect and your datasource.
The transactionmanager support can be provided by spring.
Upvotes: 0