- JPA多数据源切换 基于 SpringBoot 2.0 分析
- springboot mybatis druid 多数据源
- 从零开始学springboot-jdbc-多数据源
- Springboot2.0 + jpa + redis缓存
- spring-boot整合mybatis和druid连接池(动态
- springBoot+jpa根据实体类注解生成SQL文件
- springBoot集成多数据源mybatisPlus(自动切换
- 从零开始学springboot-配置jpa自动建表为innodb
- Spring boot2.0 spring-data-jpa使用
- SpringBoot+Mybatis+atomikos-分布式事
JPA自动装载的秘密
在SpringBoot的项目中 会有一个
spring-boot-autoconfigure 的包 通过然后查看 data.jpa 下面的就是有关Spring JPA 自动装配相关的东西
![](https://img.haomeiwen.com/i6752752/82d5c37b9acdd5b3.png)
![](https://img.haomeiwen.com/i6752752/fb6c3cda5e6181b1.png)
![](https://img.haomeiwen.com/i6752752/7483d798ba092add.png)
![](https://img.haomeiwen.com/i6752752/7e29daa6e87fc650.png)
上图显示
SpringBoot 自动装配
JpaRepositoriesAutoConfiguration
-->它导入了@Import(JpaRepositoriesAutoConfigureRegistrar.class)
JpaRepositoriesAutoConfigureRegistrar
-----> 中有个类被 EnableJpaRepositories 注解
EnableJpaRepositories -------->
中使用 entityManagerFactoryRef 和 transactionManagerRef 的默认值 分别为entityManagerFactory(entity管理)和transactionManager(事务管理)
![](https://img.haomeiwen.com/i6752752/80e29d3a0cafc4c8.png)
![](https://img.haomeiwen.com/i6752752/dbb53793d9be0472.png)
JpaRepositoriesAutoConfiguration ------->
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
------>
HibernateJpaAutoConfiguration @Import -------> HibernateJpaConfiguration
HibernateJpaConfiguration extends JpaBaseConfiguration ---->
JpaBaseConfiguration
entityManagerFactory 和 transactionManager 这个两个Bean 是通过这样注入进入的
多数据源主要涉及的Bean
Bean
- DataSource 数据源
- LocalContainerEntityManagerFactoryBean 管理Entity
- PlatformTransactionManager 事物
@Bean
@Primary
@ConfigurationProperties("spring.datasource.primary")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
读取 spring.datasource.primary 下的数据
@Bean
@Primary
@ConfigurationProperties("spring.datasource.primary")
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder().build();
}
EntityManagerFactory 注入 @Qualifier 指定数据源
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
EntityManagerFactoryBuilder builder,@Qualifier("primaryDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages(Order.class)
.properties(getVendorProperties(dataSource))
// . properties(jpaProperties.getHibernateProperties(dataSource)) // 获取并注入hibernate vender相关配置
.persistenceUnit("primary")
.build();
}
//TransactionManager Bean注入
@Bean
@Primary
public PlatformTransactionManager primaryTransactionManager(@Qualifier("primaryEntityManagerFactory") LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager(primaryEntityManagerFactory.getObject());
return transactionManager;
}
// repository 扫描的时候,并不确定哪个先扫描,查看源代码
@EnableJpaRepositories(basePackageClasses = OrderRepository.class,
entityManagerFactoryRef = "primaryEntityManagerFactory",transactionManagerRef = "primaryTransactionManager")
@Primary
public class PrimaryConfiguration {
}
多数据源配置
spring:datasource:
primary:
url: jdbc:mysql://localhost:3306/seller?user=wch&password=wch123&useUnicode=true&characterEncoding=utf-8
backup:
url: jdbc:mysql://localhost:3306/seller-backup?user=wch&password=wch123&useUnicode=true&characterEncoding=utf-8
![](https://img.haomeiwen.com/i6752752/8f968db9dcbc5014.png)
- ● 为一个LocalContainerEntityManagerFactoryBean和transactionManager的bean增加@Primary, 这样如果后面有自动配置的情况,系统能知道默认使用哪个EntityManagerFactoryBean和哪个transactionManager。
- ● @EnableJpaRepository会自动使用默认名字为entityManagerFactory的LocalContainerEntityManagerFactoryBean 和默认名字为transactionManager的TransactionManager。如果要指定多个EntityManager的情况, 需要在@EnableJpaRepositories上使用entityManagerFactoryRef和transactionManagerRef另外指定不同的LocalContainerEntityManagerFactoryBean和TransactionManager.
- ● 另外,TransactionManager必须是JpaTransactionManager!必须是JpaTransactionManager! 必须是JpaTransactionManager!入过的坑必须要说3遍。
![](https://img.haomeiwen.com/i6752752/3853f284db182f31.png)
![](https://img.haomeiwen.com/i6752752/748c91277c78de28.png)
主从JPA分别注入 Spring时 如果扫描同一个包下 两个主从只会有一个生效
修改源码 或则 分别放入两个包
修改源代码 黑科技
在本地项目中 建立和要修改的类相同的包名 和相同的类名
源码复制
tips:(当工程中有相同的类的时候,优先使用工程中的类而不再使用依赖包中的类)
在 registerRepositoriesIn 注册Bean的方法中 这段代码中加入
AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
String beanName = configurationSource.generateBeanName(beanDefinition);
AnnotationMetadata metadata = (AnnotationMetadata) configurationSource.getSource();
//判断配置类是否使用primary进行了标注,如果有,就设为primary
if(metadata.hasAnnotation(Primary.class.getName())){
beanDefinition.setPrimary(true);
}else if(metadata.hasAnnotation(RepositoryBeanNamePrefix.class.getName())){
// 再判断是否使用了RepositoryBeanNamePrefix进行了标注,如果有,添加名称前缀
Map<String,Object> prefixData = metadata.getAnnotationAttributes(RepositoryBeanNamePrefix.class.getName());
String prefix = (String) prefixData.get("value");
beanName = prefix + beanName;
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(REPOSITORY_REGISTRATION, extension.getModuleName(), beanName,
configuration.getRepositoryInterface(), configuration.getRepositoryFactoryBeanClassName());
}
![](https://img.haomeiwen.com/i6752752/73f03bde3e82502f.png)
网友评论