该模块从mybatis-mp独立而出,已经历多次迭代,可放心使用!!!
<dependency>
<groupId>cn.mybatis-mp</groupId>
<artifactId>mybatis-mp-datasource-routing</artifactId>
<version>1.0.2</version>
</dependency>
记得 加上 @EnableAspectJAutoProxy 启用aop
spring:
ds:
primary: master
routing:
master:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
master 可使用自己喜欢的
spring:
ds:
primary: master
routing:
master:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
slave:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
master、slave 可使用自己喜欢的,这里表示 一主一从的配置
spring:
ds:
primary: master
routing:
master:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
slave-1:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
slave-2:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
相当于master、slave;slave下有 slave-1,slave-2;框架自动随机slave
数据源其他属性 和 spring datasource下配置一样的
spring:
ds:
primary: master
routing:
master:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
hikari:
minimum-idle: 1
maximum-pool-size: 10
... 其他配置
更多配置 查看 hikari 官方文档
spring:
ds:
primary: master
routing:
master:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
druid:
initial-size: 1
max-active: 10
... 其他配置
更多配置 查看 druid 官方文档
spring:
ds:
primary: master
routing:
master:
username: root
password: 123456
url: jdbc:h2:mem:druidDB;INIT=RUNSCRIPT FROM 'classpath:h2-schema.sql'
other:
initial-size: 1
max-active: 10
... 其他配置
other 配置下是无提示的,具体有那么配置,需要看数据库支持那些配置; 可以 spring datasource 配置后,然后 拷贝到 other节点下。例如
spring:
datasource:
dbcp2:
connection-init-sqls: select 1
拷贝后,变成:
spring:
ds:
routing:
other:
connection-init-sqls: select 1
使用注解 @DS(数据源的名称),例如:@DS("master)
注解可以用在方法 方法,类中,方法的优先级比类高
class A{
@Resource
private B b;
@DS("master")
@Transactional
void a(){
b.b();
}
}
class B{
@DS("slave")
@Transactional
void b();
}
执行 a()方法,b方法 用的还是 master数据源;
解决方案:b方法事务改成 @Transactional(propagation = Propagation.NOT_SUPPORTED) 或 @Transactional(propagation = Propagation.REQUIRES_NEW)
class A{
@DS("master")
@Transactional
void a(){
b();
}
@DS("slave")
@Transactional
void b();
}
由于spring 代理方法时,对于同类下方法内部调用走的是类本身的方法,无法被spring代理,所以:
1:创建一个新类,然后b方法放到里边
2:使用 A a = (A)AopContext.currentProxy(); 同时:@EnableAspectJAutoProxy(exposeProxy = true) 如下:
class A{
@DS("master")
@Transactional
void a(){
A a = (A)AopContext.currentProxy();
a.b();
}
@DS("slave")
@Transactional
void b();
}
其他动态数据源框架在不接入分布式事务,也一样不支持事务一致;
无法保证事务一致性,如果需要一致性,可需要接入 其他 例如 seta 分布式事务
spring:
ds:
aop:
enabled: true
order: 1
seata: true
seata-mode: at
public class TestJdbcConfigDecryptor implements JdbcConfigDecryptor {
@Override
public String jdbcUrlDecrypt(String encryptedJdbcUrl) {
//此处进行解密
return encryptedJdbcUrl;
}
@Override
public String usernameDecrypt(String encryptedUsername) {
//此处进行解密
return "root";
}
@Override
public String passwordDecrypt(String encryptedPassword) {
//此处进行解密
return encryptedPassword;
}
}
@Configuration(proxyBeanMethods = false)
public class Config {
/**
* 创建JdbcConfig解密 Bean
*
* @return
*/
@Bean
JdbcConfigDecryptor jdbcConfigDecryptor() {
return new TestJdbcConfigDecryptor();
}
}
spring:
ds:
jdbc-config-decrypt: true
primary: master
routing:
master:
name: master
type: com.zaxxer.hikari.HikariDataSource
url: 加密后的地址
username: 加密后的username
passowrd: 加密后的password
hikari:
minimum-idle: 1
maximum-pool-size: 10