Spring 启动 JPA 设置自定义数据源
Spring boot JPA set custom datasource
我定义了 2 个数据源-
#datasource jndi setup
database.datasources[1].jndi-name=jdbc/yyyy
database.datasources[1].username=yyyy
database.datasources[1].password=yyyyy
database.datasources[1].url=jdbc:oracle:thin:@localhost:2222:webtst
database.datasources[1].driverClassName=oracle.jdbc.OracleDriver
database.datasources[1].factory=org.apache.tomcat.jdbc.pool.DataSourceFactory
database.datasources[1].initialSize=1
database.datasources[1].maxActive=5
database.datasources[0].jndi-name=jdbc/xxx
database.datasources[0].username=xxx
database.datasources[0].password=xxxx
database.datasources[0].url=jdbc:oracle:thin:@localhost:2222:webtst
database.datasources[0].driverClassName=oracle.jdbc.OracleDriver
database.datasources[0].factory=org.apache.tomcat.jdbc.pool.DataSourceFactory
database.datasources[0].initialSize=1
database.datasources[0].maxActive=15
和 2 个匹配的 JPA 存储库,在我将其中一个定义为 @Primary 之后,如何设置其中一个使用不同的 ds(不是主要的 ds):
@Bean
@Primary
DataSource dataSource() throws SQLException {
OracleDataSource dataSource = new OracleDataSource();
dataSource.setUser(xusername);
dataSource.setPassword(xpassword);
dataSource.setURL(xurl);
dataSource.setImplicitCachingEnabled(true);
dataSource.setFastConnectionFailoverEnabled(true);
return dataSource;
}
@Bean
DataSource propsDataSource() throws SQLException {
OracleDataSource propsDataSource = new OracleDataSource();
//propsDataSource.setDataSourceName(secJNDIName);
propsDataSource.setUser(yUserName);
propsDataSource.setPassword(ypropsPassword);
propsDataSource.setURL(upropsUrl);
propsDataSource.setImplicitCachingEnabled(true);
propsDataSource.setFastConnectionFailoverEnabled(true);
return propsDataSource;
}
还有一个简单的 JpaRepository,我希望它使用二级数据源:
public interface AttributesRepo extends JpaRepository<PRODUCTATTRIBUTE, PRODUCTATTRIBUTE_KEY> {
}
您需要:
- 定义两个
DataSource
- 将其中之一标记为
@Primary
(就像您所做的那样)
- 定义两个
LocalContainerEntityManagerFactoryBean
em1
和 em2
每个使用不同的 DataSource
- 定义两个
TransactionManagers
- 将所有应该使用第一个
DataSource
的存储库放入包 pkg1
中,将其他存储库放入包 pkg2
- 定义一个
@Configuration
class with @EnableJpaRepositories
with basePackages = "pkg1"
and entityManagerFactoryRef = "em1"
- 第二个
@Configuration
class 为 pkg2
和 em2
我使用两个数据源。这是我的 applicationContext.xml:
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<jpa:repositories base-package="nl.christine.schwartze.server"/>
<context:property-placeholder location="classpath:/META-INF/database.properties"/>
<context:component-scan base-package="nl.christine.schwartze.server"/>
<bean class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close" id="importDataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${importDatabase.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="defaultPU"/>
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="nl.christine.schwartze.server.model"/>
<property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/>
<property name="jpaProperties" ref="props"/>
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
</bean>
<bean id="importEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="importPU"/>
<property name="dataSource" ref="importDataSource"/>
<property name="packagesToScan" value="nl.christine.schwartze.server.modelimport"/>
<property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/>
<property name="jpaProperties" ref="importprops"/>
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="importTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="importEntityManagerFactory" />
</bean>
<bean id="hibernateVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<util:properties id="props">
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL82Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">${database.createorvalidate}</prop>
<prop key="hibernate.ddl-auto">${database.createorvalidate}</prop>
<prop key="spring.jpa.show-sql">true</prop>
<prop key="spring.jpa.generate.ddl">true</prop>
<prop key="spring.jpa.hibernate.ddl-auto">${database.createorvalidate}</prop>
<prop key="spring.datasource.initialization-mode">never</prop>
<prop key="spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation">true</prop>
</util:properties>
<util:properties id="importprops">
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.id.new_generator_mappings">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL82Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.ddl-auto">validate</prop>
<prop key="spring.jpa.show-sql">true</prop>
<prop key="spring.jpa.generate.ddl">true</prop>
<prop key="spring.jpa.hibernate.ddl-auto">validate</prop>
<prop key="spring.datasource.initialization-mode">never</prop>
<prop key="spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation">true</prop>
</util:properties>
<bean id="importLetterDao" class="nl.christine.schwartze.server.daoimport.impl.ImportLetterDaoImpl" scope="singleton">
</bean>
<bean id="letterDao" class="nl.christine.schwartze.server.dao.impl.LetterDaoImpl" scope="singleton">
</bean>
<bean id="locationDao" class="nl.christine.schwartze.server.dao.impl.LocationDaoImpl" scope="singleton">
</bean>
<bean id="personDao" class="nl.christine.schwartze.server.dao.impl.PersonDaoImpl" scope="singleton">
</bean>
<bean id="letterService" class="nl.christine.schwartze.server.service.impl.LetterServiceImpl" scope="singleton">
</bean>
<bean id="logger" scope="prototype" class="org.slf4j.LoggerFactory" factory-method="getLogger">
<constructor-arg name="name" value="schwartzeLogger" />
</bean>
这是域之一的一部分 类:
@Entity
@Table(name = "letters")
@EnableJpaRepositories(
basePackages = "nl.christine.schwartze.server.dao",
transactionManagerRef = "transactionManager",
entityManagerFactoryRef = "defaultPU")
public class Letter {
...
这些是我在控制器方法上的注释:
@CrossOrigin(origins = "http://pengo.christine.nl:3000")
@RequestMapping(method = RequestMethod.POST, value = "/get_letters/")
@Transactional("transactionManager")
public ResponseEntity<LettersResult> getLetters(@RequestBody LettersRequest request) {
...
示例项目 here。
我定义了 2 个数据源-
#datasource jndi setup
database.datasources[1].jndi-name=jdbc/yyyy
database.datasources[1].username=yyyy
database.datasources[1].password=yyyyy
database.datasources[1].url=jdbc:oracle:thin:@localhost:2222:webtst
database.datasources[1].driverClassName=oracle.jdbc.OracleDriver
database.datasources[1].factory=org.apache.tomcat.jdbc.pool.DataSourceFactory
database.datasources[1].initialSize=1
database.datasources[1].maxActive=5
database.datasources[0].jndi-name=jdbc/xxx
database.datasources[0].username=xxx
database.datasources[0].password=xxxx
database.datasources[0].url=jdbc:oracle:thin:@localhost:2222:webtst
database.datasources[0].driverClassName=oracle.jdbc.OracleDriver
database.datasources[0].factory=org.apache.tomcat.jdbc.pool.DataSourceFactory
database.datasources[0].initialSize=1
database.datasources[0].maxActive=15
和 2 个匹配的 JPA 存储库,在我将其中一个定义为 @Primary 之后,如何设置其中一个使用不同的 ds(不是主要的 ds):
@Bean
@Primary
DataSource dataSource() throws SQLException {
OracleDataSource dataSource = new OracleDataSource();
dataSource.setUser(xusername);
dataSource.setPassword(xpassword);
dataSource.setURL(xurl);
dataSource.setImplicitCachingEnabled(true);
dataSource.setFastConnectionFailoverEnabled(true);
return dataSource;
}
@Bean
DataSource propsDataSource() throws SQLException {
OracleDataSource propsDataSource = new OracleDataSource();
//propsDataSource.setDataSourceName(secJNDIName);
propsDataSource.setUser(yUserName);
propsDataSource.setPassword(ypropsPassword);
propsDataSource.setURL(upropsUrl);
propsDataSource.setImplicitCachingEnabled(true);
propsDataSource.setFastConnectionFailoverEnabled(true);
return propsDataSource;
}
还有一个简单的 JpaRepository,我希望它使用二级数据源:
public interface AttributesRepo extends JpaRepository<PRODUCTATTRIBUTE, PRODUCTATTRIBUTE_KEY> {
}
您需要:
- 定义两个
DataSource
- 将其中之一标记为
@Primary
(就像您所做的那样) - 定义两个
LocalContainerEntityManagerFactoryBean
em1
和em2
每个使用不同的DataSource
- 定义两个
TransactionManagers
- 将所有应该使用第一个
DataSource
的存储库放入包pkg1
中,将其他存储库放入包pkg2
- 定义一个
@Configuration
class with@EnableJpaRepositories
withbasePackages = "pkg1"
andentityManagerFactoryRef = "em1"
- 第二个
@Configuration
class 为pkg2
和em2
我使用两个数据源。这是我的 applicationContext.xml:
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<jpa:repositories base-package="nl.christine.schwartze.server"/>
<context:property-placeholder location="classpath:/META-INF/database.properties"/>
<context:component-scan base-package="nl.christine.schwartze.server"/>
<bean class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close" id="importDataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${importDatabase.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="defaultPU"/>
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="nl.christine.schwartze.server.model"/>
<property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/>
<property name="jpaProperties" ref="props"/>
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
</bean>
<bean id="importEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="importPU"/>
<property name="dataSource" ref="importDataSource"/>
<property name="packagesToScan" value="nl.christine.schwartze.server.modelimport"/>
<property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/>
<property name="jpaProperties" ref="importprops"/>
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="importTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="importEntityManagerFactory" />
</bean>
<bean id="hibernateVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<util:properties id="props">
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL82Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">${database.createorvalidate}</prop>
<prop key="hibernate.ddl-auto">${database.createorvalidate}</prop>
<prop key="spring.jpa.show-sql">true</prop>
<prop key="spring.jpa.generate.ddl">true</prop>
<prop key="spring.jpa.hibernate.ddl-auto">${database.createorvalidate}</prop>
<prop key="spring.datasource.initialization-mode">never</prop>
<prop key="spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation">true</prop>
</util:properties>
<util:properties id="importprops">
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.id.new_generator_mappings">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL82Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.ddl-auto">validate</prop>
<prop key="spring.jpa.show-sql">true</prop>
<prop key="spring.jpa.generate.ddl">true</prop>
<prop key="spring.jpa.hibernate.ddl-auto">validate</prop>
<prop key="spring.datasource.initialization-mode">never</prop>
<prop key="spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation">true</prop>
</util:properties>
<bean id="importLetterDao" class="nl.christine.schwartze.server.daoimport.impl.ImportLetterDaoImpl" scope="singleton">
</bean>
<bean id="letterDao" class="nl.christine.schwartze.server.dao.impl.LetterDaoImpl" scope="singleton">
</bean>
<bean id="locationDao" class="nl.christine.schwartze.server.dao.impl.LocationDaoImpl" scope="singleton">
</bean>
<bean id="personDao" class="nl.christine.schwartze.server.dao.impl.PersonDaoImpl" scope="singleton">
</bean>
<bean id="letterService" class="nl.christine.schwartze.server.service.impl.LetterServiceImpl" scope="singleton">
</bean>
<bean id="logger" scope="prototype" class="org.slf4j.LoggerFactory" factory-method="getLogger">
<constructor-arg name="name" value="schwartzeLogger" />
</bean>
这是域之一的一部分 类:
@Entity
@Table(name = "letters")
@EnableJpaRepositories(
basePackages = "nl.christine.schwartze.server.dao",
transactionManagerRef = "transactionManager",
entityManagerFactoryRef = "defaultPU")
public class Letter {
...
这些是我在控制器方法上的注释:
@CrossOrigin(origins = "http://pengo.christine.nl:3000")
@RequestMapping(method = RequestMethod.POST, value = "/get_letters/")
@Transactional("transactionManager")
public ResponseEntity<LettersResult> getLetters(@RequestBody LettersRequest request) {
...
示例项目 here。