Spring 学习

Spring Boot Jpa多数据源配置

2018-11-12  本文已影响114人  Java大生

前言

随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源,如:user一个库,business一个库。那么接下来我们就要考虑怎么去在spring boot中实现多个数据源的配置。

源码下载

实现

建表

首先是建表语句,我们要建立两个数据库,并各库内新建一张表

user表

mysql> use `user`;

mysql> select * from `user`;

+----+-------+----------+

| id | name  | password |

+----+-------+----------+

|  1 | 用户A | ******   |

+----+-------+----------+

1 row in set

business表

mysql> use `business`;

mysql> select * from `business`;

+----+-------+-------------+

| id | name  | description |

+----+-------+-------------+

|  1 | 业务A | 业务A描述   |

+----+-------+-------------+

1 row in set

接下来我们通过代码实现对两个库内的多张表进行查询。

配置

首先,创建一个Spring配置类,定义两个DataSource用来读取application.yml中的不同配置。本文中,我们user做为主数据源,主数据源配置为spring.datasource.user开头的配置,business数据源配置为spring.datasource.business开头的配置。

@Configuration

public class DataSourceConfig {

   @Primary

   @Bean(name = "userDataSource")

   @Qualifier("userDataSource")

   @ConfigurationProperties(prefix = "spring.datasource.user")

   public DataSource userDataSource() {

       return DataSourceBuilder.create().build();

   }

   @Bean(name = "businessDataSource")

   @Qualifier("businessDataSource")

   @ConfigurationProperties(prefix = "spring.datasource.business")

   public DataSource businessDataSource() {

       return DataSourceBuilder.create().build();

   }

}

对应的配置文件application.yml如下:

spring:

 datasource:

   user:

     driver-class-name: com.mysql.jdbc.Driver

     jdbc-url: jdbc:mysql://localhost:3306/user

     username: root

     password: 123456

   business:

     driver-class-name: com.mysql.jdbc.Driver

     jdbc-url: jdbc:mysql://localhost:3306/business

     username: root

     password: 123456

接下来我们对各数据源进行jpa的配置

主数据源User

@Configuration

@EnableTransactionManagement

@EnableJpaRepositories(

       entityManagerFactoryRef = "entityManagerFactoryUser",

       transactionManagerRef = "transactionManagerUser",

       //设置Repository所在位置

       basePackages = {"com.ppc.spring.example.jpamultidatasource.repository.user"})

public class UserConfig {

   @Autowired

   @Qualifier("userDataSource")

   private DataSource userDataSource;

   @Autowired

   private JpaProperties jpaProperties;

   @Autowired

   private HibernateProperties hibernateProperties;

   @Primary

   @Bean(name = "entityManagerUser")

   public EntityManager entityManager(EntityManagerFactoryBuilder builder) {

       return entityManagerFactoryUser(builder).getObject().createEntityManager();

   }

   @Primary

   @Bean(name = "entityManagerFactoryUser")

   public LocalContainerEntityManagerFactoryBean entityManagerFactoryUser(EntityManagerFactoryBuilder builder) {

       return builder

               .dataSource(userDataSource)

               //设置entity所在位置

               .packages("com.ppc.spring.example.jpamultidatasource.entity.user")

               .persistenceUnit("userPersistenceUnit")

               .properties(getVendorProperties())

               .build();

   }

   private Map<String, Object> getVendorProperties() {

       return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());

   }

   @Primary

   @Bean(name = "transactionManagerUser")

   public PlatformTransactionManager transactionManagerUser(EntityManagerFactoryBuilder builder) {

       return new JpaTransactionManager(entityManagerFactoryUser(builder).getObject());

   }

}

其他数据源business

@Configuration

@EnableTransactionManagement

@EnableJpaRepositories(

       entityManagerFactoryRef = "entityManagerFactoryBusiness",

       transactionManagerRef = "transactionManagerBusiness",

       //设置repository所在位置

       basePackages = {"com.ppc.spring.example.jpamultidatasource.repository.business"})

public class BusinessConfig {

   @Autowired

   @Qualifier("businessDataSource")

   private DataSource businessDataSource;

   @Autowired

   private JpaProperties jpaProperties;

   @Autowired

   private HibernateProperties hibernateProperties;

   @Bean(name = "entityManagerBusiness")

   public EntityManager entityManager(EntityManagerFactoryBuilder builder) {

       return entityManagerFactoryBusiness(builder).getObject().createEntityManager();

   }

   @Bean(name = "entityManagerFactoryBusiness")

   public LocalContainerEntityManagerFactoryBean entityManagerFactoryBusiness(EntityManagerFactoryBuilder builder) {

       return builder

               .dataSource(businessDataSource)

               .properties(getVendorProperties())

               //设置实体类所在位置

               .packages("com.ppc.spring.example.jpamultidatasource.entity.business")

               .persistenceUnit("businessPersistenceUnit")

               .build();

   }

   private Map<String, Object> getVendorProperties() {

       return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());

   }

   @Bean(name = "transactionManagerBusiness")

   PlatformTransactionManager transactionManagerBusiness(EntityManagerFactoryBuilder builder) {

       return new JpaTransactionManager(entityManagerFactoryBusiness(builder).getObject());

   }

}

配置中需要注意以下几点:

Spring Boot 1.5.x

private Map<String, String> getVendorProperties() {

 return jpaProperties.getHibernateProperties(userDataSource);

}

Spring Boot 2.0.x

private Map<String, Object> getVendorProperties() {

 return jpaProperties.getHibernateProperties(new HibernateSettings());

}

Spring Boot 2.1.0参见上文代码,引进了HibernateProperties。同时,在Spring Boot 2.1.0中默认的mysql-connector-java版本为8.0.13,连接低版本mysql配置上比较繁琐,建议在配置文件中手动指定相应版本,如本文中指定5.1.46这个版本。

runtimeOnly('mysql:mysql-connector-java:5.1.46')

repository、entity的所在位置,要和实际保存的位置一致。

主数据源的一些配置需要添加@Primary作为spring默认的首选项,其他数据源无需添加该注解。

通过查看相关源码我们看到Spring Boot中JpaProperties的代码一直在调整,这里我们将properties相关代码单独提取出作为一个单独的方法getVendorProperties展示版本间的区别。其中:

查询

完成了所有的配置,接下来我们就可以开始写个简单代码验证我们配置了

@RestController

@SpringBootApplication

public class JpaMultiDatasourceApplication {

   @Autowired

   UserRepository userRepository;

   @Autowired

   BusinessRepository businessRepository;

   public static void main(String[] args) {

       SpringApplication.run(JpaMultiDatasourceApplication.class, args);

   }

   @GetMapping("/user/{id}")

   public User getUser(@PathVariable Long id) {

       return userRepository.findById(id).orElse(null);

   }

   @GetMapping("/business/{id}")

   public Business getBusiness(@PathVariable Long id) {

       return businessRepository.findById(id).orElse(null);

   }

}

我们对外暴露了两个接口,分别访问user表、business表确认可以正常获取数据。查询结果如下:

请求:http://localhost:8080/user/1

结果:{"id":1,"name":"用户A","password":"******"}

请求:http://localhost:8080/business/1

结果:{"id":1,"name":"业务A","description":"业务A描述"}

就此,我们双数据源的配置和验证工作就完成了。

上一篇下一篇

猜你喜欢

热点阅读