How to setup multiple data sources with Spring and JPA
2015-01-09 10:15
525 查看
转自:http://www.codingpedia.org/ama/how-to-setup-multiple-data-sources-with-spring-and-jpa/
Contents [hide]
1. Showcase
2. Configuration
2.1.
Persistence.xml
2.2.
Spring Appplication Context
2.3. In code
3.
Testing it – optional
4. Resources
4.1. Codingpedia
4.2. GitHub
4.3. Web
In this post I will show you how to setup two or more data sources in a Spring application where the access to the database is done via JPA. It will be a XML-based Spring configuration. To highlight the setup I will use a showcase that builds on an existing
demo example I have committed on GitHub, that covers other two posts of mine
RESTful
Web Services Example in Java with Jersey, Spring and MyBatis
and
Java
Persistence Example with Spring, JPA2 and Hibernate
Don’t worry! You don’t have to understand what’s going on in those if you just want to see how the setup for multiple data sources looks like – I’ll do a quick introduction in the first part of the post.
The demo application used in the posts mentioned presents how to use a REST API to execute CRUD operations against a back-end db, delivering podcasts. For the demo’s sake I’ll say a client of
the REST API also needs resources(podcasts) from a “legacy” system – she needs to combine them with the ones from the actual system and present them to their users.
For that I will implement two new read operations that will GET the podcast(s) from the “legacy” system. The new REST facade layer –
that delivers “legacy” resources will use the same data access layer to highlight the use of multiple data sources.
Now let’s see how to configure and code multiple data sources with Spring and JPA:
The first thing I did was to modify the
data source:
Note: The persistence unit defines a set of all entity classes that are managed by
Note the persistenceUnitName property of the entityManagerFactory is pointing to the corresponding persistence unit.
Here’s a quick recap of the main configured beans:
entityManagerFactoryLegacy
a
to JPA’s standard container bootstrap contract. This is the most powerful way to set up a shared JPA EntityManagerFactory in a Spring application context; the
then be passed to JPA-based DAOs via dependency injection. Note that switching to a JNDI lookup or to a
is just a matter of
configuration!
As with
file, residing in the class path, according to the general JPA configuration contract. However, this
more flexible in that you can override the location of the persistence.xml file (as here the case), specify the JDBC DataSources to link to, etc. Furthermore, it allows for pluggable class instrumentation through Spring’s
instead of being tied to a special VM agent specified on JVM startup.
transactionManagerLegacy
a
Binds a JPA
one thread-bound EntityManager per factory.
aware of thread-bound entity managers and participate in such transactions automatically. Using either is required for JPA access code supporting this transaction management mechanism.
This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access. JTA (usually through
is necessary for accessing multiple transactional resources within the same transaction. Note that you need to configure your JPA provider accordingly in order to make it participate in JTA transactions.
As mentioned before to highlight the multiple data source configuration in code I extended the DAO layer class with methods to access the “legacy” system:
You see here how you can use multiple entity managers in the same class. And we that we conclude the configuration example of accessing multiple data sources.Code Tip – you can best see the differences to the code with one data source configuration by having a look at my GitHub commit for this post at https://github.com/amacoder/demo-restWS-spring-jersey-jpa2-hibernate/commit/f37d52d88348eb125097a561e9105d61fffa08c3
Once Jetty is started execute GET operations on the following URIs:
http://localhost:8888/demo-rest-spring-jersey-jpa2-hibernate-0.0.1-SNAPSHOT/legacy/podcasts
http://localhost:8888/demo-rest-spring-jersey-jpa2-hibernate-0.0.1-SNAPSHOT/legacy/podcasts/2
to get all podcasts, or respectively a specific podcast from the “legacy” system.
You can also have look at my video on how to test a REST API with the DEV
HTTP Client
Well, that’s it. You’ve learned how to configure multiple a Spring application to access multiple data sources via JPA.
If you’ve found it useful, please help it spread by sharing it on Twitter, Google+ or Facebook. Thank you! Don’t forget also to check out Podcastpedia.org –
you’ll find for sure interesting podcasts and episodes. We are grateful for your
support.
Java
Persistence Example with Spring, JPA2 and Hibernate
RESTful
Web Services Example in Java with Jersey, Spring and MyBatis
Tomcat
JDBC Connection Pool configuration for production and development
Source code for Java
Persistence Example with Spring, JPA2 and Hibernate ( encapsulates code for this post)
Differences
to one datasource version
StackOverflow
– Difference between configuring data source in persistence.xml and in spring configuration files
Contents [hide]
1. Showcase
2. Configuration
2.1.
Persistence.xml
2.2.
Spring Appplication Context
2.3. In code
3.
Testing it – optional
4. Resources
4.1. Codingpedia
4.2. GitHub
4.3. Web
In this post I will show you how to setup two or more data sources in a Spring application where the access to the database is done via JPA. It will be a XML-based Spring configuration. To highlight the setup I will use a showcase that builds on an existing
demo example I have committed on GitHub, that covers other two posts of mine
RESTful
Web Services Example in Java with Jersey, Spring and MyBatis
and
Java
Persistence Example with Spring, JPA2 and Hibernate
Don’t worry! You don’t have to understand what’s going on in those if you just want to see how the setup for multiple data sources looks like – I’ll do a quick introduction in the first part of the post.
1. Showcase
The demo application used in the posts mentioned presents how to use a REST API to execute CRUD operations against a back-end db, delivering podcasts. For the demo’s sake I’ll say a client ofthe REST API also needs resources(podcasts) from a “legacy” system – she needs to combine them with the ones from the actual system and present them to their users.
For that I will implement two new read operations that will GET the podcast(s) from the “legacy” system. The new REST facade layer –
PodcastLegacyRestService–
that delivers “legacy” resources will use the same data access layer to highlight the use of multiple data sources.
Now let’s see how to configure and code multiple data sources with Spring and JPA:
2. Configuration
2.1. Persistence.xml
The first thing I did was to modify the persistence.xmlfile by adding a new
persistence unitthat will correspond to the “legacy”
entityManager, managing the new “legacy”
data source:
123456789 | <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="demoRestPersistence"> <provider>org.hibernate.ejb.HibernatePersistence</provider> </persistence-unit> <persistence-unit name="demoRestPersistenceLegacy"> <provider>org.hibernate.ejb.HibernatePersistence</provider> </persistence-unit> </persistence> |
EntityManagerinstances in an application. This set of entity classes represents the data contained within a single data store.Because I am using Spring you can see the configuration of the persistence unit in the
persistence.xmlis very lean. The actual configuration of the entity managers takes places in the Spring’s application context of the application. See the next section for the details.
2.2. Spring Appplication Context
In the Spring application context I just added new beans for the entity manager, transaction manger and datasource:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="org.codingpedia.demo.rest.*" /> <!-- ************ JPA configuration *********** --> <tx:annotation-driven transaction-manager="transactionManager" /> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <bean id="transactionManagerLegacy" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactoryLegacy" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath:config/persistence-demo.xml" /> <property name="persistenceUnitName" value="demoRestPersistence" /> <property name="dataSource" ref="restDemoDS" /> <property name="packagesToScan" value="org.codingpedia.demo.*" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true" /> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> </bean> </property> </bean> <bean id="entityManagerFactoryLegacy" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath:config/persistence-demo.xml" /> <property name="persistenceUnitName" value="demoRestPersistenceLegacy" /> <property name="dataSource" ref="restDemoLegacyDS" /> <property name="packagesToScan" value="org.codingpedia.demo.*" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true" /> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> </bean> </property> </bean> <bean id="podcastDao" class="org.codingpedia.demo.rest.dao.impl.PodcastDaoJPA2Impl"/> <bean id="podcastRestService" class="org.codingpedia.demo.rest.service.PodcastRestService" /> <bean id="podcastLegacyRestService" class="org.codingpedia.demo.rest.service.PodcastLegacyRestService" /> <bean id="restDemoDS" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton"> <property name="jndiName" value="java:comp/env/jdbc/restDemoDB" /> <property name="resourceRef" value="true" /> </bean> <bean id="restDemoLegacyDS" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton"> <property name="jndiName" value="java:comp/env/jdbc/restDemoLegacyDB" /> <property name="resourceRef" value="true" /> </bean> </beans> |
Here’s a quick recap of the main configured beans:
entityManagerFactoryLegacy
(org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean)is
a
org.springframework.beans.factory.FactoryBeanthat creates a JPA
javax.persistence.EntityManagerFactoryaccording
to JPA’s standard container bootstrap contract. This is the most powerful way to set up a shared JPA EntityManagerFactory in a Spring application context; the
EntityManagerFactorycan
then be passed to JPA-based DAOs via dependency injection. Note that switching to a JNDI lookup or to a
LocalEntityManagerFactoryBeandefinition
is just a matter of
configuration!
As with
LocalEntityManagerFactoryBean, configuration settings are usually read in from a
META-INF/persistence.xmlconfig
file, residing in the class path, according to the general JPA configuration contract. However, this
FactoryBeanis
more flexible in that you can override the location of the persistence.xml file (as here the case), specify the JDBC DataSources to link to, etc. Furthermore, it allows for pluggable class instrumentation through Spring’s
org.springframework.instrument.classloading.LoadTimeWeaverabstraction,
instead of being tied to a special VM agent specified on JVM startup.
transactionManagerLegacy
(org.springframework.orm.jpa.JpaTransactionManager)is
a
org.springframework.transaction.PlatformTransactionManagerimplementation for a single JPA
javax.persistence.EntityManagerFactory.
Binds a JPA
EntityManagerfrom the specified factory to the thread, potentially allowing for
one thread-bound EntityManager per factory.
SharedEntityManagerCreatorand
JpaTemplateare
aware of thread-bound entity managers and participate in such transactions automatically. Using either is required for JPA access code supporting this transaction management mechanism.
This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access. JTA (usually through
org.springframework.transaction.jta.JtaTransactionManager)
is necessary for accessing multiple transactional resources within the same transaction. Note that you need to configure your JPA provider accordingly in order to make it participate in JTA transactions.
2.3. In code
As mentioned before to highlight the multiple data source configuration in code I extended the DAO layer class with methods to access the “legacy” system:12345678910111213141516171819202122232425262728293031323334353637383940414243 | package org.codingpedia.demo.rest.dao.impl; import java.util.Calendar;import java.util.Date;import java.util.GregorianCalendar;import java.util.List;import java.util.TimeZone; import javax.persistence.EntityManager;import javax.persistence.NoResultException;import javax.persistence.PersistenceContext;import javax.persistence.Query;import javax.persistence.TemporalType;import javax.persistence.TypedQuery; import org.codingpedia.demo.rest.dao.PodcastDao;import org.codingpedia.demo.rest.entities.Podcast; public class PodcastDaoJPA2Impl implements PodcastDao { @PersistenceContext(unitName="demoRestPersistence") private EntityManager entityManager; @PersistenceContext(unitName="demoRestPersistenceLegacy") private EntityManager entityManagerLegacy; public List<Podcast> getPodcasts() { String qlString = "SELECT p FROM Podcast p"; TypedQuery<Podcast> query = entityManager.createQuery(qlString, Podcast.class); return query.getResultList(); } /* .............................*/ public List<Podcast> getLegacyPodcasts() { String qlString = "SELECT p FROM Podcast p"; TypedQuery<Podcast> query = entityManagerLegacy.createQuery(qlString, Podcast.class); return query.getResultList(); } } |
3. Testing it – optional
To test the new “legacy” functionality you can start the jetty server configured in thepom.xml, file by issuing the following maven command in the root directory of the project:
1 | mvn jetty:run -Djetty.port=8888 |
http://localhost:8888/demo-rest-spring-jersey-jpa2-hibernate-0.0.1-SNAPSHOT/legacy/podcasts
http://localhost:8888/demo-rest-spring-jersey-jpa2-hibernate-0.0.1-SNAPSHOT/legacy/podcasts/2
to get all podcasts, or respectively a specific podcast from the “legacy” system.
You can also have look at my video on how to test a REST API with the DEV
HTTP Client
Well, that’s it. You’ve learned how to configure multiple a Spring application to access multiple data sources via JPA.
If you’ve found it useful, please help it spread by sharing it on Twitter, Google+ or Facebook. Thank you! Don’t forget also to check out Podcastpedia.org –
you’ll find for sure interesting podcasts and episodes. We are grateful for your
support.
4. Resources
4.1. Codingpedia
JavaPersistence Example with Spring, JPA2 and Hibernate
RESTful
Web Services Example in Java with Jersey, Spring and MyBatis
Tomcat
JDBC Connection Pool configuration for production and development
4.2. GitHub
Source code for JavaPersistence Example with Spring, JPA2 and Hibernate ( encapsulates code for this post)
Differences
to one datasource version
4.3. Web
StackOverflow– Difference between configuring data source in persistence.xml and in spring configuration files
相关文章推荐
- How to setup multiple data sources with Spring and JPA
- Google Merchant How To Setup A Live XML Data Feed With MySql and PHP
- Distributed transactions with multiple databases, Spring Boot, Spring Data JPA and Atomikos
- Distributed transactions with multiple databases, Spring Boot, Spring Data JPA and Atomikos
- How to setup multiple sites hosted on your Mac with OSX 10.8 + (MAMP Part 5)
- How To Save Your App Data With NSCoding and NSFileManager
- How to setup a GIT server with gitosis and gitweb
- how-to create a high-availability mysql setup with corosync pacemaker and drbd on ubuntu
- 3 ways to do WCF Concurrency Management(Single, Multiple, and Reentrant and How to do with Throttling)
- How To Read and Write BLOB Data by Using ADO.NET with Visual C# .NET
- 深入浅出学Spring Data JPA toPredicate Predicate[] p = new Predicate[list.size()]; query.where(cb.and 201
- how to select data in multiple datatables after using join,group by and order by in Linq
- How To Setup a Rails 4 App With Apache and Passenger on CentOS 6
- How to provide highlighting with Spring data elasticsearch
- How To Read and Write BLOB Data by Using ADO.NET with Visual C# .NET
- How to Create a High Availability Setup with Pacemaker, Corosync and Floating IPs on CentOS 7
- How to setup Eclipse with WinAVR and the Eclipse plugin AVR-eclipse
- spring.data.jpa.query :Cannot use native queries with dynamic sorting and/or pagination in method
- How to create iOS 8 Today extension and share data with containing app – tutorial
- How to bind a GridView to a list of multiple types? NHibernate proxy causing problems with databinding [From stack overflow]