配置多数据源
- SpringBoot v2.0.5.RELEASE
- SpringDataJPA 2.0.10RELEASE
- Hibernate-Core:5.2.17
- JPA参数详解
- 问题
- 1.Spring Data Jpa 自定义 Repository EntityManager is null
- yml配置
- JPA
- 初始化数据源
- master 和slave各自的JPA详细配置
- @EnableJpaRepositories
SpringBoot v2.0.5.RELEASE
SpringDataJPA 2.0.10RELEASE
Hibernate-Core:5.2.17
JPA参数详解
问题
1.Spring Data Jpa 自定义 Repository EntityManager is null
这个问题是啊我在查询资料过程中搜到,本身我并未遇到,在此记录以下
新版本中去除了 @PersistenceContext 注解, 无法自动进行注入, 应该是新版本为了支持微服务, 表分库策略,
可以使用多个数据源, 多个EntityManager, 故移除自动注入, 改为手动注入:
@Autowired
public CustomerRepositoryImpl(JpaContext context){
super(Customer.class);
setEntityManager(context.getEntityManagerByManagedType(Follow.class));
}
yml配置
spring:
datasource:
# 第一个数据源
primary:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/primary?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8
username: root
password: 123456
# 第二数据源
secondary:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/secondary?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8
username: root
password: 123456
JPA
初始化数据源
@Configuration
@Slf4j
public class DataSourceConfig {
@Primary
@Bean(name = "masterDataSourceProperties")
@Qualifier(value = "masterDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSourceProperties masterDataSourceProperties(){
return new DataSourceProperties();
}
@Primary
@Bean(name = "masterDataSource")
@Qualifier(value = "masterDataSource")
public DataSource masterDataSource(){
log.info("创建master数据源");
return masterDataSourceProperties().initializeDataSourceBuilder().build();
}
@Bean(name = "salveDataSourceProperties")
@Qualifier(value = "salveDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.salve")
public DataSourceProperties salveDataSourceProperties(){
return new DataSourceProperties();
}
@Bean(name = "salveDataSource")
@Qualifier(value = "salveDataSource")
public DataSource salveDataSource(){
log.info("创建slave数据源");
return salveDataSourceProperties().initializeDataSourceBuilder().build();
}
}
master 和slave各自的JPA详细配置
@Configuration
@Component
@ComponentScan({"com.test.config"})
@EnableTransactionManagement
@EnableJpaRepositories(
//默认关闭事务,启动类上的注释掉了,在这里补充上
enableDefaultTransactions = false,
entityManagerFactoryRef = "masterEntityManagerFactoryBean", //配置实体管理器连接工厂
transactionManagerRef = "masterTransactionManager", //配置事务管理器
basePackages = {"com.test.repository"
}, //repository位置
//排除使用salve库的接口
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
slaveTestRepository.class
})
}
)
public class MasterDataSourceConfig {
@Autowired
@Qualifier(value = "masterDataSource")
private DataSource masterDataSource;
@Autowired
private JpaProperties jpaProperties;
//配置entityManager实体
@Primary
@Bean(name = "masterEntityManager")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return Objects.requireNonNull(entityManagerFactoryBeanMaster(builder).getObject()).createEntityManager();
}
@Primary
@Bean(name = "masterEntityManagerFactoryBean")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanMaster(EntityManagerFactoryBuilder builder) {
return builder.dataSource(masterDataSource) //设置数据源
.properties(getVendorProperties()) // hibernate配置
.properties(jpaProperties.getProperties())//jpa配置
.persistenceUnit("masterPersistenceUnit") //设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源
.packages("com.test.entity",
) //设置实体类所在位置
.build();
}
@Primary
@Bean(name = "masterTransactionManager")
public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(Objects.requireNonNull(entityManagerFactoryBeanMaster(builder).getObject()));
}
//jpa配置信息
public Map<String, String> getProperties() {
HashMap<String, String> map = Maps.newHashMap();
map.put("show-sql", "true");
map.put("hibernate.ddl-auto", "none");
map.put("hibernate.naming-strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
map.put("hibernate.dialect", "org.hibernate.dialect.MySQL55Dialect");
return map;
}
private Map<String,Object> getVendorProperties() {
//return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
return jpaProperties.getHibernateProperties(new HibernateSettings());
}
/**getVendorProperties() 函数的调试信息
* {hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy,
* hibernate.format_sql=true,
* hibernate.hbm2ddl.auto=update,
* hibernate.id.new_generator_mappings=true,
* hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy,
* hibernate.dialect=org.hibernate.dialect.MySQL55Dialect}
*/
}
主数据源设置如此,从数据源相同
- 配置实体管理器连接工厂时指定了持久化单元名,用于
- @PersistenceContext注解获取EntityManager时指定数据源
- 在我使用过程中,当类中注入了EntityManager entityManager自定义查询方法时,必须用@PersistenceContext来注入,不能用@Autowired;
如果@PersistenceContext()未指定参数,那么这个实体管理器默认使用master数据源,指定后才会使用指定的实体管理器;- 如果直接使用SpringDataJPA已经封装好的查询方法,比如findbyId()这是候会根据配置JPA配置类的扫描包配置信息使用指定数据源
- 启动类上不要再使用@EnableJpaRepositories,在数据源JPA配置类上使用此注解
必须使用@Primary指定主数据源
@EnableJpaRepositories
1 @EnableJpaRepositories(
2 basePackages = {},
3 basePackageClasses = {},
4 includeFilters = {},
5 excludeFilters = {},
6 repositoryImplementationPostfix = "Impl",
7 namedQueriesLocation = "",//META-INF/jpa-named-queries.properties
8 queryLookupStrategy=QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND, //QueryLookupStrategy.Key.x
9 repositoryFactoryBeanClass=JpaRepositoryFactoryBean.class, //class
10 entityManagerFactoryRef="entityManagerFactory",
11 transactionManagerRef="transactionManager",
12 considerNestedRepositories=false,
13 enableDefaultTransactions=true
14 )
属性 | 缺省值 | 描述 |
value | basePackages的别名,简化basePackages | |
basePackages | 用于配置扫描Repositories所在的包。填写字符串(或字符串数组)形式的包名. | |
basePackageClasses | basePackages的安全替代选选项。指定一个要扫描包中的一个类或接口,将扫描所在包中的所有repository,可以考虑在每个要扫描的包中创建一个类或接口,它除了被这个属性引用外,没有其他用途。 | |
includeFilters | 指定哪些类型的组件被扫描。过滤器,该过滤区采用ComponentScan的过滤器类 | |
excludeFilters | 指定哪些类型的组件不被扫描。 | |
repositoryImplementationPostfix | impl | 查找自定义存储库实现时要使用的后缀。默认为Impl。对于名为PersonRepository的存储库,将通过扫描PersonRepositoryImpl来查找相应的实现类。 |
namedQueriesLocation | META-INF/jpa-named-queries.properties | 配置Spring-Data的named queries 属性文件的位置,默认META-INF/jpa-named-queries.properties。 |
queryLookupStrategy | QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND | 查询方法的查询策略。构建条件查询的策略,包含三种方式CREATE USE_DECLARED_QUERY,CREATE_IF_NOT_FOUND CREATE:按照接口名称自动构建查询 USE_DECLARED_QUERY:用户声明查询CREATE_IF_NOT_FOUND:先搜索用户声明的,不存在则自动构建 |
repositoryFactoryBeanClass | JpaRepositoryFactoryBean | 用于每个存储库实例的FactoryBean类。默认为JpaRepositoryFactoryBean。 |
repositoryBaseClass | 配置存储库基类,以用于为该特定配置创建存储库代理。 | |
entityManagerFactoryRef | entityManagerFactory | 配置EntityManagerFactory bean定义的名称。默认为entityManagerFactory。 |
transactionManagerRef | transactionManager | 配置PlatformTransactionManager bean定义的名称。默认为transactionManager。 |
considerNestedRepositories | false | 配置是否发现嵌套的Repository接口(如定义为内部类)。默认为false。 |
enableDefaultTransactions | true | 配置Spring-Data-Jpa 的Repositories是否启用默认事务,默认为true。如果禁用,则必须在外层使用。 |
bootstrapMode | BootstrapMode.DEFAULT | 配置在引导生命周期中何时初始化Repository。默认为BootstrapMode.DEFAULT,除了添加了BootstrapMode.LAZY的接口外,其他接口立即初始化。1. BootstrapMode.LAZY,Repository的bean定义被认为是懒加载注入,并且只在首次使用时初始化,即应用程序可能在没有初始化Repository的情况下完全启动 2. BootstrapMode.DEFERRED,Repository的bean定义被认为是懒加载注入,但存储库初始化在应用程序上下文引导完成时触发。 |
escapeCharacter | 配置在包含contains、startsWith或endsWith子句的派生查询中用于转义 _ 或 % 的通配符字符。 |
参考资料: