SoFunction
Updated on 2025-03-08

Solve the problem of configuring multiple data sources in spring boot 1.5.4

spring boot already supports multi-data source configuration, without the need for many of the online types to write, which is particularly troublesome. Check out the following solutions, official ones, don’t worry!

1. First define the data source configuration

#=====================multiple database config============================
#ds1
=jdbc:mysql://localhost/test?characterEncoding=utf8&useSSL=true
=root
=123456
-class-name=
=
-wait=10000
-active=200
-on-borrow=true
-size=10

#ds2
=jdbc:mysql://localhost/test2?characterEncoding=utf8&useSSL=true
=root
=123456
-class-name=
=
-wait=10000
-active=200
-on-borrow=true
-size=10

#=====================jpa config================================
#The specific behavior of entity class maintaining database table structure: update/create/create-drop/validate/none-auto=none
#Print SQL statement-sql=true
#Format output json string.indent_output=true

2. Configure the related injection objects of ds1 and enable jpa support

/**
  * Created by hdwang on 2017-06-16.
  * The first data source configuration
  * If you are using Spring Data, you need to configure @EnableJpaRepositories
  */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "",entityManagerFactoryRef = "firstEntityManagerFactory",transactionManagerRef="firstTransactionManager")
public class FirstDsConfig {

  /**
    * Data source configuration object
    * Primary represents the default object. Autowire can inject it, not the default name must be injected.
    * @return
    */
  @Bean
  @Primary
  @ConfigurationProperties("")
  public DataSourceProperties firstDataSourceProperties() {
    return new DataSourceProperties();
  }

  /**
    * Data source object
    * @return
    */
  @Bean
  @Primary
  @ConfigurationProperties("")
  public DataSource firstDataSource() {
    return firstDataSourceProperties().initializeDataSourceBuilder().build();
  }

  /**
    * Entity management object
    * @param builder Inject this object from spring, first inject according to type (multiple objects that declare @Primary), otherwise inject according to name
    * @return
    */
  @Bean
  @Primary
  public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(
      EntityManagerFactoryBuilder builder) {
    return builder
        .dataSource(firstDataSource())
        .packages("")
        .persistenceUnit("firstDs")
        .build();
  }

  /**
    * Transaction management object
    * @return
    */
  @Bean(name = "firstTransactionManager")
  @Primary
  public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    (emf);
    return transactionManager;
  }

  @Bean
  @Primary
  public JdbcTemplate jdbcTemplate(){
    return new JdbcTemplate(firstDataSource());
  }

  @Bean
  @Primary
  public TransactionTemplate transactionTemplate(PlatformTransactionManager platformTransactionManager){
    return new TransactionTemplate(platformTransactionManager);
  }
}

Related knowledge points:

1. Use @Bean to create a bean object and hand it over to the spring container management

2. The name of the bean object created by @Bean is the method name by default, and it can also be specified.

3. @Bean method parameter indicates that when receiving a bean object, the injected object is received according to the type type by default. If you want to modify it to the byName method, you can use the @Qualifier annotation to inject accurate objects.

4. @Primary means that the bean is the default bean of this type. When referenced in other places, use @Autowired to inject according to the type, and is not affected by multiple objects of the same type.

Indicates enabling spring data jpa support, that is, the new way of using jpa. Pay attention to what basePackages refers to. The package location of @Repository interface can be configured with multiple

Other annotations are not clear!

2. Configure the related injection objects of ds2 and enable jpa support

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "", entityManagerFactoryRef = "secondEntityManagerFactory",transactionManagerRef = "secondTransactionManager")
public class SecondDsConfig {

  @Bean
  @ConfigurationProperties("")
  public DataSourceProperties secondDataSourceProperties() {
    return new DataSourceProperties();
  }

  @Bean
  @ConfigurationProperties("")
  public DataSource secondDataSource() {
    return secondDataSourceProperties().initializeDataSourceBuilder().build();
  }

  /**
    * Entity management object
    * @param builder Inject this object from spring, first inject according to type (multiple objects that declare @Primary), otherwise inject according to name
    * @return
    */
  @Bean
  public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory(
      EntityManagerFactoryBuilder builder) {
    return builder
        .dataSource(secondDataSource())
        .packages("")
        .persistenceUnit("secondDs")
        .build();
  }

  /**
    * Things management object
    * @param secondEntityManagerFactory Entity Management Factory Objects (injected by name)
    * @return Platform Things Manager
    */
  @Bean(name = "secondTransactionManager")
  public PlatformTransactionManager transactionManager(@Qualifier("secondEntityManagerFactory")LocalContainerEntityManagerFactoryBean secondEntityManagerFactory){
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    (());
    return transactionManager;
  }

  @Bean(name="jdbcTemplate2")
  public JdbcTemplate jdbcTemplate(){
    return new JdbcTemplate(secondDataSource());
  }

  @Bean(name = "transactionTemplate2")
  public TransactionTemplate transactionTemplate(@Qualifier("secondTransactionManager")PlatformTransactionManager transactionManager){
    return new TransactionTemplate(transactionManager);
  }
}

Data persistence layer

package ;

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
  /**
    * spring data jpa will automatically inject implementation (according to method naming specification)
    * @return
    */
  User findByNumber(String number);


  @Modifying
  @Query("delete from User u where  = :id")
  void deleteUser(@Param("id")int id);
}
package ;

@Repository
public interface OrderRepository extends JpaRepository<Order, Integer> {
  /**
    * spring data jpa will automatically inject implementation (according to method naming specification)
    * @return
    */
  User findByNumber(String number);


  @Modifying
  @Query("delete from Order o where  = :id")
  void deleteUser(@Param("id") int id);
}

The above two interfaces belong to two data sources. After @EnableJpaRepositories is configured, the corresponding data sources can be operated correctly here.

Service layer, pay attention to things (I won’t post the interface)

@Service
@Transactional("firstTransactionManager")
public class UserServiceImpl implements UserService {

  @Autowired
  private UserRepository userRepository;

  @Override
  public User findById(int id) {
    return (id);
  }

  @Override
  public User findByNumber(String number) {
    return (number);
  }

  @Override
  public List<User> findAllUserByPage(int page,int size) {
    Pageable pageable = new PageRequest(page, size);
    Page<User> users = (pageable);
    return ();
  }

  @Override
  public User updateUser(User user,boolean throwEx) {
    User userNew = (user);
    if(throwEx){
      throw new RuntimeException("throw a ex");
    }
    return userNew;
  }

  @Override
  public void deleteUser(int id) {
    (id);
  }
}
@Service
@Transactional("secondTransactionManager")
public class OrderServiceImpl implements OrderService {

  @Autowired
  private OrderRepository orderRepository;


  @Override
  public Order findById(int id) {
    return (id);
  }

  @Override
  public Order updateOrder(Order order, boolean throwEx) {
    Order orderNew = (order);
    if(throwEx){
      throw new RuntimeException("throw a ex");
    }
    return orderNew;
  }
}

Knowledge extension

1. If you adopt the traditional jpa method, @EnableJpaRepositories does not require configuration, and it will not affect the configuration. The implementation method is as follows:

ds1 related DaoImpl
@PersistenceContext
private EntityManager entityManager;

ds2 related DaoImpl
@PersistenceContext(unitName = "secondDs")
private EntityManager entityManager;

Because ds1's entityManger declares @Primary, there is no need to specify unitName, ds2 must specify. After injecting the accurate entityManager, you can use it directly to operate the database. The service layer is the same as above, @Transactional("xxxManager") just specify the thing manager!

2. Use jdbcTemplate method and directly inject it into the Service layer object, so easy!

@Autowired
private JdbcTemplate jdbcTemplate;

@Autowired
private TransactionTemplate transactionTemplate;

@Resource(name="jdbcTemplate2")
private JdbcTemplate jdbcTemplate2;

@Resource(name="transactionTemplate2")
private TransactionTemplate transactionTemplate2;

OK, spring boot has multiple data sources, perfect solution! Moreover, all three database operation methods are supported, including things. It has been proven by practice! This is the best practice given by the official, but the official documentation is not detailed. It caused me to cheat for a few days. At this point, the use of the spring boot framework has come to an end!

The above article solves the problem of configuring multiple data sources in spring boot 1.5.4 is all the content I share with you. I hope you can give you a reference and I hope you can support me more.