多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] # 多数据源的支持 ## 同源数据库的多源支持 日常项目中因为使用的分布式开发模式,不同的服务有不同的数据源,常常需要在一个项目中使用多个数据源,因此需要配置sping data jpa对多数据源的使用,一般分一下为三步: 1. 创建数据库 test1 和 test2 2. 配置多数据源 3. 不同源的 repository 放⼊不同包路径 4. 声明不同的包路径下使⽤不同的数据源、事务⽀持 不同的包路径下创建对应的 repository 5. 测试使⽤ **配置两个数据源** ~~~ spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true spring.datasource.primary.username=root spring.datasource.primary.password=root spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true spring.datasource.secondary.username=root spring.datasource.secondary.password=root spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver #spring.jpa.show-sql=true #SQL 输出 spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.hbm2ddl.auto=create spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect #format ⼀下 SQL 进⾏输出 spring.jpa.properties.hibernate.format_sql=true ~~~ **配置数据源** 创建 DataSourceConfig 添加 @Configuration 注解,在项⽬启动时运⾏初始化数据库资源 ~~~ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import javax.sql.DataSource; import java.util.Map; @Configuration public class DataSourceConfig { @Autowired private JpaProperties jpaProperties; @Autowired private HibernateProperties hibernateProperties; //加载第一个数据源 @Bean(name = "primaryDataSource") @Primary @ConfigurationProperties("spring.datasource.primary") public DataSource firstDataSource() { return DataSourceBuilder.create().build(); } //加载第二个数据源 @Bean(name = "secondaryDataSource") @ConfigurationProperties("spring.datasource.secondary") public DataSource secondDataSource() { return DataSourceBuilder.create().build(); } //加载 JPA 的相关配置信息,JpaProperties 是 JPA 的⼀些属性配置信息,构建 LocalEntityManagerFactoryBean 需要参数信息注⼊到⽅法中。 @Bean(name = "vendorProperties") public Map<String, Object> getVendorProperties() { return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()); } } ~~~ **第⼀个数据源的加载配置过程** ⾸先来看第⼀个数据源的加载配置过程,创建 PrimaryConfig 类,将上⾯创建好的第⼀个数据源注⼊到类中,添加 @Configuration 和 @EnableTransactionManagement 注解,第⼀个代表启动时加载,第⼆个注解 表示启⽤事务,同时将第⼀个数据源和 JPA 配置信息注⼊到类中。 ~~~ import java.util.Map; import javax.persistence.EntityManager; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; //将我们在类中配置好的 EntityManager 和事务信息注⼊到对应数据源的 repository ⽬录 下,这样此⽬录下的 repository 就会拥有对应数据源和事务的信息 @Configuration //启动时加载 @EnableTransactionManagement //启用事务 @EnableJpaRepositories( entityManagerFactoryRef="entityManagerFactoryPrimary", transactionManagerRef="transactionManagerPrimary", basePackages= { "com.neo.repository.test1" }) //设置dao(repo)所在位置, basePackages ⽀持设置多个包路径 public class PrimaryConfig { @Autowired @Qualifier("primaryDataSource") private DataSource primaryDataSource; @Autowired @Qualifier("vendorProperties") private Map<String, Object> vendorProperties; //LocalEntityManagerFactoryBean 负责创建⼀个适合于仅使⽤ JPA 进⾏数据访问的环境的 EntityManager, 构建的时候需要指明提示实体类的包路径、数据源和 JPA 配置信息 @Bean(name = "entityManagerFactoryPrimary") @Primary public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) { return builder .dataSource(primaryDataSource) .properties(vendorProperties) .packages("com.neo.model") //设置实体类所在位置 .persistenceUnit("primaryPersistenceUnit") .build(); } //利⽤上⾯的 entityManagerFactoryPrimary() ⽅法构建好最终的 EntityManager //EntityManager 是 JPA 中⽤于增、删、改、查的接⼝,它的作⽤相当于⼀座桥梁,连接内存中的 Java 对象 和数据库的数据存储。使⽤ EntityManager 中的相关接⼝对数据库实体进⾏操作的时候, EntityManager 会 跟踪实体对象的状态,并决定在特定时刻将对实体的操作映射到数据库操作上⾯。 @Bean(name = "entityManagerPrimary") @Primary public EntityManager entityManager(EntityManagerFactoryBuilder builder) { return entityManagerFactoryPrimary(builder).getObject().createEntityManager(); } //给数据源添加上 JPA 事务 @Bean(name = "transactionManagerPrimary") @Primary PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject()); } } ~~~ **第二个数据源的加载配置过程** 第⼆个数据源配置和第⼀个数据源配置类似,只是⽅法上去掉了注解:@Primary,第⼆个数据源数据源加载 配置类 SecondaryConfig 完整代码如下: ~~~ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.persistence.EntityManager; import javax.sql.DataSource; import java.util.Map; @Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef="entityManagerFactorySecondary", transactionManagerRef="transactionManagerSecondary", basePackages= { "com.neo.repository.test2" }) public class SecondaryConfig { @Autowired @Qualifier("secondaryDataSource") private DataSource secondaryDataSource; @Autowired @Qualifier("vendorProperties") private Map<String, Object> vendorProperties; @Bean(name = "entityManagerFactorySecondary") public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) { return builder .dataSource(secondaryDataSource) .properties(vendorProperties) .packages("com.neo.model") .persistenceUnit("secondaryPersistenceUnit") .build(); } @Bean(name = "entityManagerSecondary") public EntityManager entityManager(EntityManagerFactoryBuilder builder) { return entityManagerFactorySecondary(builder).getObject().createEntityManager(); } @Bean(name = "transactionManagerSecondary") PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject()); } } ~~~ ## 异构数据库多源支持 比如我们的项目中,即需要对mysql的支持,也需要对mongodb的查询等。 实体类声明`@Entity`关系型数据库支持类型、声明`@Document`为mongodb支持类型,不同的数据源使用不同的实体就可以了 ~~~ interface PersonRepository extends Repository<Person, Long> { … } @Entity public class Person { … } interface UserRepository extends Repository<User, Long> { … } @Document public class User { … } ~~~ 但是,如果User用户既使用mysql也使用mongodb呢,也可以做混合使用 ~~~ interface JpaPersonRepository extends Repository<Person, Long> { … } interface MongoDBPersonRepository extends Repository<Person, Long> { … } @Entity @Document public class Person { … } ~~~ 也可以通过对不同的包路径进行声明,比如A包路径下使用mysql,B包路径下使用mongoDB ~~~ @EnableJpaRepositories(basePackages = "com.neo.repositories.jpa") @EnableMongoRepositories(basePackages = "com.neo.repositories.mongo") interface Configuration { } ~~~