用Java基于Spring框架搭建一套支持多数据源的web系统框架

在使用Java Spring框架搭建支持多数据源的Web系统框架时,你可以按照以下步骤进行:

步骤一:添加依赖

首先,在pom.xml文件中添加Spring Boot和相关数据库依赖:

XML 复制代码
<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- 数据库驱动依赖,例如MySQL -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>

步骤二:配置多数据源

  1. 创建多个数据源配置类,每个数据源对应一个数据库连接:
java 复制代码
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {

    @Bean(name = "dataSource1")
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "entityManagerFactory1")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory1(
            EntityManagerFactoryBuilder builder,
            @Qualifier("dataSource1") DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.domain.datasource1")
                .persistenceUnit("datasource1")
                .build();
    }

    @Bean(name = "transactionManager1")
    public PlatformTransactionManager transactionManager1(
            @Qualifier("entityManagerFactory1") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}
  1. 配置 application.properties 文件,设置多数据源的连接信息:

    java 复制代码
    ## 数据源1配置
    spring.datasource.datasource1.url=jdbc:mysql://localhost:3306/db1
    spring.datasource.datasource1.username=root
    spring.datasource.datasource1.password=rootPassword
    spring.datasource.datasource1.driver-class-name=com.mysql.cj.jdbc.Driver
    
    ## 数据源2配置
    spring.datasource.datasource2.url=jdbc:mysql://localhost:3306/db2
    spring.datasource.datasource2.username=root
    spring.datasource.datasource2.password=rootPassword
    spring.datasource.datasource2.driver-class-name=com.mysql.cj.jdbc.Driver

    步骤三:定义实体类和Repository

  2. 创建实体类和对应的Repository接口,分别对应不同的数据源。

步骤四:创建Controller

编写Controller类,处理业务逻辑,并根据需要调用不同数据源的Repository。

java 复制代码
@Configuration
public class DataSourceConfig {

    @Primary
    @Bean(name = "dataSource1")
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "entityManagerFactory1")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory1(EntityManagerFactoryBuilder builder,
                                                                       @Qualifier("dataSource1") DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.entity1")
                .persistenceUnit("dataSource1")
                .build();
    }

    @Bean(name = "transactionManager1")
    public PlatformTransactionManager transactionManager1(@Qualifier("entityManagerFactory1") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Bean(name = "dataSource2")
    @ConfigurationProperties(prefix = "spring.datasource.datasource2")
    public DataSource dataSource2() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "entityManagerFactory2")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory2(EntityManagerFactoryBuilder builder,
                                                                       @Qualifier("dataSource2") DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.entity2")
                .persistenceUnit("dataSource2")
                .build();
    }

    @Bean(name = "transactionManager2")
    public PlatformTransactionManager transactionManager2(@Qualifier("entityManagerFactory2") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

在这段代码中,我们配置了两个数据源(dataSource1dataSource2),每个数据源都有对应的实体管理工厂(entityManagerFactory1entityManagerFactory2)以及事务管理器(transactionManager1transactionManager2)。

步骤五:使用多数据源

在服务或业务逻辑中,根据需要使用不同的数据源。可以通过在Repository中指定数据源的方式来实现:

java 复制代码
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // 使用第一个数据源
}
java 复制代码
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    // 使用第二个数据源
}

步骤六:配置多数据源交换

在需要切换数据源的地方,可以使用@Primary@Qualifier注解来指定使用哪个数据源。比如在Service层或Controller层中:

java 复制代码
@Service
public class UserService {
    
    @Autowired
    @Qualifier("userRepository")
    private UserRepository userRepository;

    // 使用第一个数据源的Repository操作数据
}
java 复制代码
@Service
public class ProductService {

    @Autowired
    @Qualifier("productRepository")
    private ProductRepository productRepository;

    // 使用第二个数据源的Repository操作数据
}

步骤七:测试多数据源功能

最后,通过编写测试用例来验证多数据源的功能是否正常工作。可以分别测试不同数据源的读写操作,以确保整个系统的多数据源支持已经成功搭建。在这段代码中,我们使用了@EnableJpaRepositories注解分别为两个数据源配置了不同的JpaRepository包路径、实体管理工厂引用和事务管理器引用。这样就可以确保每个数据源的JpaRepository都能正确地与对应的实体管理工厂和事务管理器关联起来。

java 复制代码
@EnableJpaRepositories(
        basePackages = "com.example.repository1",
        entityManagerFactoryRef = "entityManagerFactory1",
        transactionManagerRef = "transactionManager1"
)
public class DataSource1JpaConfig {
    // 这里配置针对dataSource1的JpaRepository
}
java 复制代码
@EnableJpaRepositories(
        basePackages = "com.example.repository2",
        entityManagerFactoryRef = "entityManagerFactory2",
        transactionManagerRef = "transactionManager2"
)
public class DataSource2JpaConfig {
    // 这里配置针对dataSource2的JpaRepository
}

当需要在多数据源环境下执行事务管理时,需要进行额外的配置以确保事务能够正确地跨多个数据源进行管理。

步骤八:配置多数据源事务管理

  1. 创建一个事务管理器工厂类,用于创建支持多数据源的事务管理器:

    java 复制代码
    @Configuration
    public class TransactionManagerConfig {
    
        @Bean
        @Primary
        public PlatformTransactionManager transactionManager(
                @Qualifier("dataSource1TransactionManager") PlatformTransactionManager dataSource1TransactionManager,
                @Qualifier("dataSource2TransactionManager") PlatformTransactionManager dataSource2TransactionManager) {
            ChainedTransactionManager transactionManager = new ChainedTransactionManager(
                    dataSource1TransactionManager, dataSource2TransactionManager);
            return transactionManager;
        }
    }
  2. 在需要进行事务管理的Service方法上添加 @Transactional 注解,以确保事务能够正确地跨多个数据源进行管理。

    java 复制代码
    @Service
    public class MultiDataSourceService {
    
        @Autowired
        private UserRepository userRepository;
    
        @Autowired
        private ProductRepository productRepository;
    
        @Transactional(transactionManager = "transactionManager")
        public void transferBetweenDataSources(User user, Product product) {
            // 在此方法中进行跨数据源的业务操作
            userRepository.save(user);
            productRepository.save(product);
        }
    }

    步骤九:测试多数据源事务管理

    编写测试用例来验证多数据源事务管理的功能是否正常工作。可以模拟跨数据源的业务操作,并验证事务是否能够正确地回滚或提交。

    java 复制代码
    @Service
    public class MultiDataSourceService {
    
        @Autowired
        private UserRepository userRepository;
    
        @Autowired
        private ProductRepository productRepository;
    
        @Transactional(transactionManager = "transactionManager")
        public void transferBetweenDataSources(User user, Product product) {
            // 在第一个数据源保存用户信息
            userRepository.save(user);
    
            // 模拟异常情况,使第二个数据源保存产品信息时出现错误
            if (product.getName().equals("error")) {
                throw new RuntimeException("Error occurred while saving product");
            }
    
            // 在第二个数据源保存产品信息
            productRepository.save(product);
        }
    }

    在这段代码中,我们定义了一个MultiDataSourceService服务类,其中的transferBetweenDataSources方法模拟了一个跨数据源的业务操作:先在第一个数据源保存用户信息,然后在第二个数据源保存产品信息。如果产品名称为"error",则会抛出运行时异常。

    通过在该方法上添加@Transactional(transactionManager = "transactionManager")注解,确保了事务能够正确地跨多个数据源进行管理。当出现异常时,事务会回滚,保证数据的一致性。

相关推荐
CoderIsArt31 分钟前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck1 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei1 小时前
java的类加载机制的学习
java·学习
师太,答应老衲吧3 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Yaml43 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~3 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616883 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
Channing Lewis4 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
aloha_7894 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot