SpringBoot应用多数据源支持嗡汤圆的小笔记.docx
- 文档编号:26150641
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:10
- 大小:17.22KB
SpringBoot应用多数据源支持嗡汤圆的小笔记.docx
《SpringBoot应用多数据源支持嗡汤圆的小笔记.docx》由会员分享,可在线阅读,更多相关《SpringBoot应用多数据源支持嗡汤圆的小笔记.docx(10页珍藏版)》请在冰豆网上搜索。
SpringBoot应用多数据源支持嗡汤圆的小笔记
SpringBoot应用多数据源支持[嗡汤圆的小笔记]
在某些应用场景中,SpringBoot应用可能需要同时连接多个数据源(同类型或不同类型数据库)进行数据处理和写入操作。
下文将配置多数据源(两个Postgres数据库)为例进行说明。
其中:
*数据库-1维护表1,表3
*数据库-2维护表2,表3
*分别说明如何分别往表1,表2(各库独占表)写数据,以及分别往数据库-1的表3、数据库-2的表3写入不同的数据。
1、项目搭建
基础步骤,在start.spring.io中勾选JPA,JDBC,POSTGRESSQL组件,下载基础MAVEN项目。
并导入IDE即可。
已经建好的项目和样例代码请见链接:
SpringBootMultipleDataSource
1.1、基础配置
刚构建好的项目包含spring-data相关组件,因此无初始配置时,会提示缺少默认配置而无法启动。
以下演示配置过程。
1.1.1、Properties文件配置
在application.properties声明数据源配置,分别包括数据库one,数据库two,和通用jpa设置。
spring.datasource.one.url=jdbc:
postgresql:
//localhost:
5432/testdb1
spring.datasource.one.username=postgres
spring.datasource.one.password=password
spring.datasource.one.driverClassName=org.postgresql.Driver
spring.datasource.two.url=jdbc:
postgresql:
//localhost:
5432/testdb2
spring.datasource.two.username=postgres
spring.datasource.two.password=password
spring.datasource.two.driverClassName=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true12345678910111213
1.1.2、Bean声明
由于存在两个数据源,因此不能使用Springboot的默认数据配置方式,而是自行声明bean。
SpirngBoot的数据源组件(包含jpa)声明层级如下:
DataSource->EntityManager->TransactionManager
这些组件声明都可以写在一个类中,方便管理。
(1)Datasource
设置了各数据库的连接方式与参数,结合Spring的配置文件自动注入方式来分别声明两个数据源。
/*通过不同的配置参数前缀来分别为不同datasource赋予参数*/
@Bean
@Primary
@ConfigurationProperties(prefix="spring.datasource.one")
publicDataSourceprimaryDataSource(){
returnDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix="spring.datasource.two")
publicDataSourcesecondaryDataSource(){
returnDataSourceBuilder.create().build();
}123456789101112
(2)EntityManager
通过EntityManagerFactoryBuild->EntityManagerFactory,用于以后声明EntityManager使用。
EntityManager定义了所使用的数据源,和所扫描的Entity包路径(packages)。
EntityManager仅管理包路径下的Entity,以达到在不同数据源管理不同表的目的。
例子中的表1位于tbdsone包下,表3位于tbdsboth包下,表2位于tdbstwo包下。
而两个EntityManager均管理tbdsboth,因此表3在两个数据源中都存在。
@Bean(name="primaryEMFB")
@Primary
publicLocalContainerEntityManagerFactoryBean
primaryEntityManagerFactory(EntityManagerFactoryBuilderbuilder){
returnbuilder.dataSource(primaryDataSource())
.packages("com.rails.demoapp.core.module.tbdsboth",
"com.rails.demoapp.core.module.tbdsone")
.persistenceUnit("primary")
.properties(buildProperties()).build();
}
@Bean(name="secondaryEMFB")
publicLocalContainerEntityManagerFactoryBean
secondaryEntityManagerFactory(EntityManagerFactoryBuilderbuilder){
returnbuilder.dataSource(primaryDataSource())
.packages("com.rails.demoapp.core.module.tbdsboth",
"com.rails.demoapp.core.module.tbdstwo")
.persistenceUnit("secondary")
.properties(buildProperties()).build();
}
//公共jpa设置
@Value("${spring.jpa.hibernate.ddl-auto}")
Stringdll;
@Value("${spring.jpa.properties.hibernate.dialect}")
Stringdialect;
@Value("${spring.jpa.show-sql}")
StringshowSql;
privateMapbuildProperties(){
Mapproperties=newHashMap();
properties.put("hibernate.ejb.naming_strategy",ImprovedNamingStrategy.class.getName());
properties.put("hibernate.hbm2ddl.auto",dll);
properties.put("hibernate.dialect",dialect);
properties.put("hibernate.show_sql",showSql);
returnproperties;
}1234567891011121314151617181920212223242526272829303132333435
(3)TransactionManager
TransactionManager用于事务管理,基于EntityManager创建。
@Bean(name="primaryTM")
@Autowired
publicPlatformTransactionManagerprimaryTransactionManager(EntityManagerFactoryBuilderbuilder){
returnnewJpaTransactionManager(primaryEntityManagerFactory(builder).getObject());
}
@Bean(name="secondaryTM")
@Autowired
publicPlatformTransactionManager
secondaryTransactionManager(EntityManagerFactoryBuilderbuilder){
returnnewJpaTransactionManager(primaryEntityManagerFactory(builder).getObject());
}1234567891011
1.2、启动效果
可以在两个Postgres数据库中看到:
testdb1中包含table1,table3;testdb2中包含table2,table3。
即可说明两个EntityManager分别在不同数据库中创建了自己所管理的表。
2、应用开发
2.1、Dao层
首先创建公共Dao层用于编写基础的增删改查操作代码。
传统的单数据源代码结构大致如下:
/*通过接口定义操作,以及实现类编写具体代码*/
publicInterfaceCommonDao{
TfindById(Objectid)throwsException;
Listquery(Stringsql)throwsException;
Tsave(Objectt)throwsException;
Tupdate(Objectt)throwsException;
voiddelete(Objectt)throwsException;
}
publicclassCommonDaoImplimplementsCommonDao{
//由于只有一个entityManager,因此用Autowired注入默认即可
@Autowired
EntityManagerem;
@Override
TfindById(Objectid)throwsException{
return(T)em.find(this.getPersistentClass(),id);
}
@Override
Listquery(Stringsql)throwsException{
Queryquery=em.createNativeQuery(sql);
Listresults=query.getResultList();
returnresults;
}
//......
//以下省略......
}123456789101112131415161718192021222324252627
但是在多数据源场景下,需要调用不同的EntityManager来操作不同数据库,因此需要在提取出一个虚类来,代码结构如下:
/*通过接口定义操作,以及抽象类编写具体代码,在实现类中注入各自的entityManager*/
publicInterfaceCommonDao{
TfindById(Objectid)throwsException;
Listquery(Stringsql)throwsException;
Tsave(Objectt)throwsException;
Tupdate(Objectt)throwsException;
voiddelete(Objectt)throwsException;
}
/*统一的实现代码虚类*/
publicabstractclassAbsCommonDaoImplimplementsCommonDao{
//引入的EntityManager由具体的实现类引入,上例代码中的em变量统一通过getEntityManager()方法获取。
abstractEntityManagergetEntityManager();
@Override
TfindById(Objectid)throwsException{
return(T)getEntityManager().find(this.getPersistentClass(),id);
}
@Override
Listquery(Stringsql)throwsException{
Queryquery=getEntityManager().createNativeQuery(sql);
Listresults=query.getResultList();
returnresults;
}
//......
//以下省略......
}
/*各数据源对应的实现类如下*/
//数据源-1
@Repository("PrimaryCommonDaoImpl")
publicclassPrimaryCommonDaoImplextendsAbsCommonDaoImpl{
//注入数据库-1的EntityManager
@Autowired
@Qualifier("primaryEMFB")
protectedEntityManagerem;
@Override
EntityManagergetEntityManager(){
returnem;
}
}
//数据源-2
@Repository("ScondaryCommonDaoImpl")
publicclassScondaryCommonDaoImplextendsAbsCommonDaoImpl{
//注入数据库-2的EntityManager
@Autowired
@Qualifier("secondaryEMFB")
protectedEntityManagerem;
@Override
EntityManagergetEntityManager(){
returnem;
}
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
具体到某张表的Dao时,则通过继承实体类来实现基本功能如有张表为TableOne,它仅在数据源-1中使用,则Dao如下:
publicInterfaceTableOneDaoextendsCommonDao{
//这里写针对TableOne的操作
}
@Repository("TableOneDaoImpl")
publicClassTableOneDaoImplextendsPrimaryCommonDaoImplimplementsTableOneDao{
//针对TableOneDao接口声明方法的实现代码
}1234567
2.2、Service层
Service层用于实现复杂业务逻辑,以及事务管理。
通用Service设计如下:
publicInterfaceCommonService{
TfindById(Objectid)throwsException;
Listquery(Stringsql)throwsException;
Tsave(Objectt)throwsException;
Tupdate(Objectt)throwsException;
voiddelete(Objectt)throwsException;
}
//由于具体表的实现需要制定具体的Dao,因此在这里无需实现公用的ServiceImpl,仅对接口做一下定义即可。
12345678
某张具体表的实现类如下:
@Service("TableOneServiceImpl")
publicTableOneServiceImplextendsCommonService{
//tableOneDaoImpl已经指定了使用数据源-1
@Resource(name="TableOneDaoImpl")
privateTableOneDaotableOneDao;
//以实现save方法为例说明Transactional的声明方法
//!
!
!
这里的@Transactional注解不是原先单数据源时的Transactional
//而是org.springframework.transaction.annotation.Transactional
//这点需要注意,否则不支持下边的参数
@Transactional("primaryTM")//通过beanname制定具体的transactionManager
@Override
TableOnesave(Objectt)throwsException{
returntableOneDao.save(t);
}
}12345678910111213141516
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SpringBoot 应用 多数 支持 汤圆 笔记