一、基础多数据源配置
1. 添加依赖
org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java
2. 配置多个数据源
# 主数据源 spring.datasource.primary.url=jdbc:mysql://localhost:3306/db1 spring.datasource.primary.username=root spring.datasource.primary.password=123456 spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.driver # 次数据源 spring.datasource.secondary.url=jdbc:mysql://localhost:3306/db2 spring.datasource.secondary.username=root spring.datasource.secondary.password=123456 spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.driver
3. 配置数据源bean
@configuration public class datasourceconfig { // 主数据源 @bean @primary @configurationproperties(prefix="spring.datasource.primary") public datasource primarydatasource() { return datasourcebuilder.create().build(); } // 次数据源 @bean @configurationproperties(prefix="spring.datasource.secondary") public datasource secondarydatasource() { return datasourcebuilder.create().build(); } }
二、jpa多数据源配置
1. 配置主数据源jpa
@configuration @enabletransactionmanagement @enablejparepositories( basepackages = "com.example.repository.primary", entitymanagerfactoryref = "primaryentitymanagerfactory", transactionmanagerref = "primarytransactionmanager" ) public class primaryjpaconfig { @autowired @qualifier("primarydatasource") private datasource primarydatasource; @primary @bean public localcontainerentitymanagerfactorybean primaryentitymanagerfactory( entitymanagerfactorybuilder builder) { return builder .datasource(primarydatasource) .packages("com.example.entity.primary") .persistenceunit("primarypersistenceunit") .properties(jpaproperties()) .build(); } private mapjpaproperties() { map props = new hashmap<>(); props.put("hibernate.hbm2ddl.auto", "update"); props.put("hibernate.dialect", "org.hibernate.dialect.mysql8dialect"); return props; } @primary @bean public platformtransactionmanager primarytransactionmanager( @qualifier("primaryentitymanagerfactory") entitymanagerfactory emf) { return new jpatransactionmanager(emf); } }
2. 配置次数据源jpa
@configuration @enabletransactionmanagement @enablejparepositories( basepackages = "com.example.repository.secondary", entitymanagerfactoryref = "secondaryentitymanagerfactory", transactionmanagerref = "secondarytransactionmanager" ) public class secondaryjpaconfig { @autowired @qualifier("secondarydatasource") private datasource secondarydatasource; @bean public localcontainerentitymanagerfactorybean secondaryentitymanagerfactory( entitymanagerfactorybuilder builder) { return builder .datasource(secondarydatasource) .packages("com.example.entity.secondary") .persistenceunit("secondarypersistenceunit") .properties(jpaproperties()) .build(); } private mapjpaproperties() { map props = new hashmap<>(); props.put("hibernate.hbm2ddl.auto", "update"); props.put("hibernate.dialect", "org.hibernate.dialect.mysql8dialect"); return props; } @bean public platformtransactionmanager secondarytransactionmanager( @qualifier("secondaryentitymanagerfactory") entitymanagerfactory emf) { return new jpatransactionmanager(emf); } }
三、mybatis多数据源配置
1. 主数据源配置
@configuration @mapperscan( basepackages = "com.example.mapper.primary", sqlsessionfactoryref = "primarysqlsessionfactory" ) public class primarymybatisconfig { @primary @bean @configurationproperties(prefix = "spring.datasource.primary") public datasource primarydatasource() { return datasourcebuilder.create().build(); } @primary @bean public sqlsessionfactory primarysqlsessionfactory( @qualifier("primarydatasource") datasource datasource) throws exception { sqlsessionfactorybean sessionfactory = new sqlsessionfactorybean(); sessionfactory.setdatasource(datasource); sessionfactory.setmapperlocations( new pathmatchingresourcepatternresolver() .getresources("classpath:mapper/primary/*.xml")); return sessionfactory.getobject(); } @primary @bean public sqlsessiontemplate primarysqlsessiontemplate( @qualifier("primarysqlsessionfactory") sqlsessionfactory sqlsessionfactory) { return new sqlsessiontemplate(sqlsessionfactory); } }
2. 次数据源配置
@configuration @mapperscan( basepackages = "com.example.mapper.secondary", sqlsessionfactoryref = "secondarysqlsessionfactory" ) public class secondarymybatisconfig { @bean @configurationproperties(prefix = "spring.datasource.secondary") public datasource secondarydatasource() { return datasourcebuilder.create().build(); } @bean public sqlsessionfactory secondarysqlsessionfactory( @qualifier("secondarydatasource") datasource datasource) throws exception { sqlsessionfactorybean sessionfactory = new sqlsessionfactorybean(); sessionfactory.setdatasource(datasource); sessionfactory.setmapperlocations( new pathmatchingresourcepatternresolver() .getresources("classpath:mapper/secondary/*.xml")); return sessionfactory.getobject(); } @bean public sqlsessiontemplate secondarysqlsessiontemplate( @qualifier("secondarysqlsessionfactory") sqlsessionfactory sqlsessionfactory) { return new sqlsessiontemplate(sqlsessionfactory); } }
四、动态数据源配置(运行时切换)
1. 抽象路由数据源
public class dynamicdatasource extends abstractroutingdatasource { @override protected object determinecurrentlookupkey() { return datasourcecontextholder.getdatasourcetype(); } }
2. 数据源上下文持有者
public class datasourcecontextholder { private static final threadlocalcontextholder = new threadlocal<>(); public static void setdatasourcetype(string datasourcetype) { contextholder.set(datasourcetype); } public static string getdatasourcetype() { return contextholder.get(); } public static void cleardatasourcetype() { contextholder.remove(); } }
3. 配置动态数据源
@configuration public class dynamicdatasourceconfig { @bean @configurationproperties(prefix="spring.datasource.primary") public datasource primarydatasource() { return datasourcebuilder.create().build(); } @bean @configurationproperties(prefix="spring.datasource.secondary") public datasource secondarydatasource() { return datasourcebuilder.create().build(); } @primary @bean public datasource dynamicdatasource( @qualifier("primarydatasource") datasource primarydatasource, @qualifier("secondarydatasource") datasource secondarydatasource) { map
4. 使用aop切换数据源
@aspect @component public class datasourceaspect { @pointcut("@annotation(com.example.annotation.targetdatasource)") public void datasourcepointcut() {} @before("datasourcepointcut()") public void before(joinpoint point) { methodsignature signature = (methodsignature) point.getsignature(); method method = signature.getmethod(); targetdatasource ds = method.getannotation(targetdatasource.class); if (ds == null) { datasourcecontextholder.setdatasourcetype("primary"); } else { datasourcecontextholder.setdatasourcetype(ds.value()); } } @after("datasourcepointcut()") public void after(joinpoint point) { datasourcecontextholder.cleardatasourcetype(); } }
5. 自定义注解
@target({elementtype.method, elementtype.type}) @retention(retentionpolicy.runtime) @documented public @interface targetdatasource { string value() default "primary"; }
6. 使用示例
@service public class userservice { @autowired private usermapper usermapper; // 使用主数据源 public user getprimaryuser(long id) { return usermapper.selectbyid(id); } // 使用次数据源 @targetdatasource("secondary") public user getsecondaryuser(long id) { return usermapper.selectbyid(id); } }
五、多数据源事务管理
1. jta分布式事务(atomikos)
org.springframework.boot spring-boot-starter-jta-atomikos
2. 配置jta数据源
# 主数据源 spring.jta.atomikos.datasource.primary.unique-resource-name=primaryds spring.jta.atomikos.datasource.primary.xa-data-source-class-name=com.mysql.cj.jdbc.mysqlxadatasource spring.jta.atomikos.datasource.primary.xa-properties.url=jdbc:mysql://localhost:3306/db1 spring.jta.atomikos.datasource.primary.xa-properties.user=root spring.jta.atomikos.datasource.primary.xa-properties.password=123456 # 次数据源 spring.jta.atomikos.datasource.secondary.unique-resource-name=secondaryds spring.jta.atomikos.datasource.secondary.xa-data-source-class-name=com.mysql.cj.jdbc.mysqlxadatasource spring.jta.atomikos.datasource.secondary.xa-properties.url=jdbc:mysql://localhost:3306/db2 spring.jta.atomikos.datasource.secondary.xa-properties.user=root spring.jta.atomikos.datasource.secondary.xa-properties.password=123456
3. 使用分布式事务
@service public class orderservice { @transactional // 跨数据源事务 public void placeorder(order order) { // 操作主数据源 primaryrepository.save(order); // 操作次数据源 auditrepository.logorder(order); // 如果此处抛出异常,两个操作都会回滚 } }
六、最佳实践
命名规范:
- 为每个数据源使用清晰的命名(如customerds, orderds)
- 包结构按数据源分离(com.example.repository.primary / .secondary)
连接池配置:
spring.datasource.primary.hikari.maximum-pool-size=10 spring.datasource.secondary.hikari.maximum-pool-size=5
监控指标:
- 为每个数据源配置独立的监控
- 使用spring actuator暴露数据源健康指标
性能考虑:
- 高频访问的数据源使用更大的连接池
- 读写分离场景考虑主从数据源
测试策略:
- 为每个数据源编写独立的测试类
- 测试跨数据源事务的回滚行为
七、常见问题解决
问题1:循环依赖
// 解决方法:使用@dependson @bean @dependson("dynamicdatasource") public platformtransactionmanager transactionmanager() { return new datasourcetransactionmanager(dynamicdatasource()); }
问题2:mybatis缓存冲突
// 解决方法:为每个sqlsessionfactory配置独立的缓存环境 sqlsessionfactory.setconfiguration(configuration); configuration.setenvironment(new environment( "primaryenv", transactionfactory, datasource ));
问题3:事务传播行为异常
// 解决方法:明确指定事务管理器 @transactional(transactionmanager = "primarytransactionmanager") public void primaryoperation() {...}
通过以上配置,spring boot应用可以灵活地支持多数据源场景,无论是简单的多库连接还是复杂的动态数据源切换需求。根据实际业务场景选择最适合的配置方式,并注意事务管理和性能调优。
以上就是springboot多数据源配置完整指南的详细内容,更多关于springboot多数据源配置的资料请关注代码网其它相关文章!
海报
186