SpringBoot 多数据源配置
spring 多数据源配置一般有两种方案:
1、在spring项目启动的时候直接配置两个不同的数据源,不同的sessionFactory。在dao 层根据不同业务自行选择使用哪个数据源的session来操作。
2、配置多个不同的数据源,使用一个sessionFactory,在业务逻辑使用的时候自动切换到不同的数据源,有一个种是在拦截器里面根据不同的业务现切换到不同的datasource;有的会在业务层根据业务来自动切换。但这种方案在多线程并发的时候会出现一些问题,需要使用threadlocal等技术来实现多线程竞争切换数据源的问题。
【我就只讨论第一种方案】
spring多事务配置主要体现在db配置这块,配置不同的数据源和不同的session
1、pom.xml核心包:
org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis-spring-boot-starter.version}
com.alibaba
druid
${druid.version}
org.springframework.boot
spring-boot-starter-jta-atomikos
2、application.yml属性配置:
spring:
datasource:
one:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.206:3306/testOne?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false
username: root
password: 1234
two:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.206:3306/testTwo?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false
username: root
password: 1234
3、接收数据源①:dataSource的Properties
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource.one")
public class OneDataSourceProperties {
private String driverClassName;
private String url;
private String username;
private String password;
}
4、设置①:dataSource
@Configuration
@MapperScan(basePackages = "com.xin.dream.one.dao", sqlSessionTemplateRef = "oneSqlSessionTemplate")
public class OneDatabaseConfig {
@Autowired
public OneDataSourceProperties oneDataSourceProperties;
@Primary
@Bean(name = "oneDataSource", destroyMethod = "close")
public DataSource oneDataSource() {
DruidXADataSource datasource = new DruidXADataSource();
BeanUtils.copyProperties(oneDataSourceProperties,datasource);
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(datasource);
xaDataSource.setUniqueResourceName("oneDataSource");
return xaDataSource;
}
@Primary
@Bean(name = "oneSqlSessionFactory")
public SqlSessionFactory oneSqlSessionFactory(@Qualifier("oneDataSource") DataSource oneDataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(oneDataSource);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:com/xin/dream/one/mapper/*.xml"));
return bean.getObject();
}
@Primary
@Bean(name = "oneSqlSessionTemplate")
public SqlSessionTemplate oneSqlSessionTemplate(
@Qualifier("oneSqlSessionFactory") SqlSessionFactory oneSqlSessionFactory) throws Exception {
return new SqlSessionTemplate(oneSqlSessionFactory);
}
}
5、第②数据源和①的步骤一样,改掉别名,和去掉@Primary,就好了。这个时候事务已经是被管理的了
在开发中遇见问题
配置文件:
spring:
jta:
atomikos:
datasource:
oneData:
max-pool-size: 25
min-pool-size: 3
max-lifetime: 20000
xa-data-source-class-name: com.alibaba.druid.pool.xa.DruidXADataSource
borrow-connection-timeout: 10000
unique-resource-name: fs
xa-properties:
password: 1234
username: root
url: jdbc:mysql://192.168.1.206:3306/testOne?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false
twoData:
max-pool-size: 25
min-pool-size: 3
max-lifetime: 20000
xa-data-source-class-name: com.alibaba.druid.pool.xa.DruidXADataSource
unique-resource-name: party
borrow-connection-timeout: 10000
xa-properties:
password: 1234
username: root
url: jdbc:mysql://192.168.1.206:3306/testOne?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false
enabled: true
为了节减代码量dataSource配置文件为:
@Configuration
@MapperScan(basePackages = "com.xin.dream.one.dao", sqlSessionTemplateRef = "oneSqlSessionTemplate")
public class OneDatabaseConfig {
@Primary
@Bean(name = "oneDataSource", destroyMethod = "close")
@ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.oneData")
public DataSource oneDataSource() {
return new AtomikosDataSourceBean();
}
@Primary
@Bean(name = "oneSqlSessionFactory")
public SqlSessionFactory oneSqlSessionFactory(@Qualifier("oneDataSource") DataSource oneDataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(oneDataSource);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:com/xin/dream/one/mapper/*.xml"));
return bean.getObject();
}
@Primary
@Bean(name = "oneSqlSessionTemplate")
public SqlSessionTemplate oneSqlSessionTemplate(
@Qualifier("oneSqlSessionFactory") SqlSessionFactory oneSqlSessionFactory) throws Exception {
return new SqlSessionTemplate(oneSqlSessionFactory);
}
}
当有多个数据源的时候报错:
Caused by: com.atomikos.jdbc.AtomikosSQLException: Cannot initialize AtomikosDataSourceBean
at com.atomikos.jdbc.AtomikosSQLException.throwAtomikosSQLException(AtomikosSQLException.java:46) ~[transactions-jdbc-3.9.3.jar:na]
at com.atomikos.jdbc.AbstractDataSourceBean.init(AbstractDataSourceBean.java:306) ~[transactions-jdbc-3.9.3.jar:na]
at org.springframework.boot.jta.atomikos.AtomikosDataSourceBean.afterPropertiesSet(AtomikosDataSourceBean.java:49) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
... 80 common frames omitted
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_131]
at com.atomikos.beans.PropertyUtils.setDirectProperty(PropertyUtils.java:205) ~[atomikos-util-3.9.3.jar:na]
at com.atomikos.beans.PropertyUtils.setProperty(PropertyUtils.java:110) ~[atomikos-util-3.9.3.jar:na]
at com.atomikos.beans.PropertyUtils.setProperties(PropertyUtils.java:186) ~[atomikos-util-3.9.3.jar:na]
at com.atomikos.jdbc.AtomikosDataSourceBean.doInit(AtomikosDataSourceBean.java:196) ~[transactions-jdbc-3.9.3.jar:na]
at com.atomikos.jdbc.AbstractDataSourceBean.init(AbstractDataSourceBean.java:296) ~[transactions-jdbc-3.9.3.jar:na]
... 83 common frames omitted
我跟踪了源码,水平有限,暂时还没弄懂原因,想直接new AtomikosDataSourceBean()或者简单的赋值,怎么弄?望朋友们指点下?