In the last article, we introduced the implementation of multi-source configuration when using the JdbcTemplate for data access. Let’s continue to learn how to configure and use multiple Data sources while using Spring Data JPA.

Add the configuration of multiple data sources

Start by setting up the two database configurations you want to link to in the Spring Boot configuration file application.properties, for example:

spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1 spring.datasource.primary.username=root spring.datasource.primary.password=123456 spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2 spring.datasource.secondary.username=root spring.datasource.secondary.password=123456 spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver # Jpa. show-sql=true # Hibernate's DDL policy Spring.jpa.hibernate. DDL -auto=create-dropCopy the code

This is exactly the same as the data source configuration in the JdbcTemplate configuration, except for the JPA configuration itself

Notes and Notes:

  1. The differences between multi-source configuration and single-source configuration are as followsspring.datasourceThen set one more data source nameprimaryandsecondaryTo distinguish between different data source configurations. This prefix will be used later when initializing the data source.
  2. Data source connection configuration 2.x and 1.x configuration items are different: 2.x usesspring.datasource.secondary.jdbc-url, while the 1.x version is usedspring.datasource.secondary.url. If this error occurs while you are configuringjava.lang.IllegalArgumentException: jdbcUrl is required with driverClassName., then it is this configuration item that is the problem.

Initialize the data source and JPA configuration

After configuring the multiple data sources, create a configuration class to load the configuration information, initialize the data sources, and the JdbcTemplate to initialize each data source.

Since the JPA configuration is much more responsible than the JdbcTemplate configuration, we split the configuration up:

  1. Create a separate multi-source configuration class, such as the following:
@Configuration public class DataSourceConfiguration { @Primary @Bean @ConfigurationProperties(prefix = "spring.datasource.primary") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); }}Copy the code

You can see that the content is exactly the same as the JdbcTemplate. By @ ConfigurationProperties can know the two data sources respectively loaded spring. The datasource. Primary. * and spring in the datasource. Secondary. * configuration. The @primary annotation specifies the Primary data source, so when we do not specify which data source, we use this Bean on the JPA configuration below.

  1. Create the JPA configuration for the two data sources separately.

JPA configuration for Primary data source:

@Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef="entityManagerFactoryPrimary", transactionManagerRef="transactionManagerPrimary", BasePackages = {com. Didispace. Chapter38. "p"}) / / set the Repository location public class PrimaryConfig {@autowired @Qualifier("primaryDataSource") private DataSource primaryDataSource; @Autowired private JpaProperties jpaProperties; @Autowired private HibernateProperties hibernateProperties; private Map<String, Object> getVendorProperties() { return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()); } @Primary @Bean(name = "entityManagerPrimary") public EntityManager entityManager(EntityManagerFactoryBuilder builder) { return entityManagerFactoryPrimary(builder).getObject().createEntityManager(); } @Primary @Bean(name = "entityManagerFactoryPrimary") public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) { return builder .dataSource(primaryDataSource) Packages (com. Didispace. Chapter38. "p") / / set the position of the entity class. PersistenceUnit (" primaryPersistenceUnit ") .properties(getVendorProperties()) .build(); } @Primary @Bean(name = "transactionManagerPrimary") public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject()); }}Copy the code

JPA configuration of Secondary data source:

@Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef="entityManagerFactorySecondary", transactionManagerRef="transactionManagerSecondary", BasePackages = {com. Didispace. Chapter38. "s"}) / / set the Repository location public class SecondaryConfig {@autowired @Qualifier("secondaryDataSource") private DataSource secondaryDataSource; @Autowired private JpaProperties jpaProperties; @Autowired private HibernateProperties hibernateProperties; private Map<String, Object> getVendorProperties() { return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()); } @Bean(name = "entityManagerSecondary") public EntityManager entityManager(EntityManagerFactoryBuilder builder) { return entityManagerFactorySecondary(builder).getObject().createEntityManager(); } @Bean(name = "entityManagerFactorySecondary") public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) { return builder .dataSource(secondaryDataSource) Packages (com. Didispace. Chapter38. "s") / / set the position of the entity class. PersistenceUnit (" secondaryPersistenceUnit ") .properties(getVendorProperties()) .build(); } @Bean(name = "transactionManagerSecondary") PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject()); }}Copy the code

Notes and Notes:

  • When using JPA, you need to create different packages for different data sources to hold the corresponding Entity and Repository to facilitate the configuration of partition scans for classes
  • Annotations on class names@EnableJpaRepositoriesSpecifies the location of the Repository in
  • LocalContainerEntityManagerFactoryBeanAt creation time, specify the location of the Entity
  • In the case of mutual injection, the naming of different data sources with different configurations is basically no big problem

Test the

With the above done, we can write a test class to see if the above multi-data source configuration is correct, such as the following:

@Slf4j @RunWith(SpringRunner.class) @SpringBootTest public class Chapter38ApplicationTests { @Autowired private UserRepository userRepository; @Autowired private MessageRepository messageRepository; @Test public void test() throws Exception { userRepository.save(new User("aaa", 10)); userRepository.save(new User("bbb", 20)); userRepository.save(new User("ccc", 30)); userRepository.save(new User("ddd", 40)); userRepository.save(new User("eee", 50)); Assert.assertEquals(5, userRepository.findAll().size()); messageRepository.save(new Message("o1", "aaaaaaaaaa")); messageRepository.save(new Message("o2", "bbbbbbbbbb")); messageRepository.save(new Message("o3", "cccccccccc")); Assert.assertEquals(3, messageRepository.findAll().size()); }}Copy the code

Notes and Notes:

  • The logic of the test validation is simply to insert data from different repositories to different data sources and then query the total to see if it is correct
  • The details of Entity and Repository are omitted here, and you can download the complete example in the code sample below for comparison

Code sample

For an example of this article, see the chapter3-8 directory in the repository below:

  • Github:github.com/dyc87112/Sp…
  • Gitee:gitee.com/didispace/S…

If you think this article is good, welcome Star support, your attention is my motivation!

reading

  • Spring Boot 1.x Basics: Configuring Multiple Data Sources

    Spring Boot 2. X Basic tutorial: Spring Data JPA multi-source configuration. Welcome to pay attention to my official account: Program ape DD, for exclusive learning resources and daily dry goods push. If you are interested in my other topics, direct them to my personal blog: didispace.com.