Spring Boot动态数据库连接Spring Data JPA

Spring Boot动态数据库连接是一种将应用程序连接到不同数据库的技术,它允许您在运行时动态选择数据库。 在Spring Boot应用程序中,您可以使用配置文件来设置数据库连接,但这样做的问题是您必须重新启动应用程序才能使用新的数据库。 要实现动态数据库连接,您可以使用Spring Data JPA框架,它提供了一个通用的Repository接口来访问数据库,并且可以使用注解来指定要连接到哪个数据库。 以下是一个使用Spring Boot和Spring Data JPA来实现动态数据库连接的示例: 1. 首先,您需要在您的pom.xml文件中添加以下依赖:
 
<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2. 接下来,您需要在您的应用程序配置文件中添加数据库连接信息。您可以添加多个数据源,并为每个数据源指定唯一的名称。
 
spring.datasource.url=jdbc:mysql://localhost:3306/db1
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

dynamic.datasource.datasource1.url=jdbc:mysql://localhost:3306/db2
dynamic.datasource.datasource1.username=root
dynamic.datasource.datasource1.password=password
dynamic.datasource.datasource1.driver-class-name=com.mysql.jdbc.Driver
3. 创建一个动态数据源配置类,用于在运行时选择要使用的数据库。
 
public class DynamicDataSourceConfig {

    @Bean
    @ConfigurationProperties("dynamic.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource")
    public DataSource dataSource() {
        return dataSourceProperties().initializeDataSourceBuilder().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "dynamic.datasource")
    public Map<String, DataSourceProperties> dataSourcePropertiesMap() {
        return new HashMap<>();
    }

    @Bean
    public AbstractRoutingDataSource routingDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        DataSource primaryDataSource = dataSource();
        targetDataSources.put("primary", primaryDataSource);

        dataSourcePropertiesMap().forEach((key, value) -> {
            DataSource dataSource = value.initializeDataSourceBuilder().build();
            targetDataSources.put(key, dataSource);
        });

        AbstractRoutingDataSource dataSource = new AbstractRoutingDataSource() {
            @Override
            protected Object determineCurrentLookupKey() {
                return DynamicDataSourceContextHolder.getDataSourceKey();
            }
        };

        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(primaryDataSource);
        return dataSource;
    }
}
4. 创建一个数据源上下文持有者类,用于在线程范围内存储当前要使用的数据源。
 
public class DynamicDataSourceContextHolder {

    private static final ThreadLocal<String> CONTEXT_HOLDER = ThreadLocal.withInitial(() -> "primary");

    public static void setDataSourceKey(String dataSourceKey) {
        CONTEXT_HOLDER.set(dataSourceKey);
    }

    public static String getDataSourceKey() {
        return CONTEXT_HOLDER.get();
    }

    public static void clearDataSourceKey() {
        CONTEXT_HOLDER.remove();
    }
}
5. 创建一个切面类,用于在访问数据库之前切换数据源。
 
public class DynamicDataSourceAspect {

    @Pointcut("@annotation(com.example.demo.dynamicdatasource.annotation.DataSource)")
    public void dataSourcePointcut() {
    }

    @Around("dataSourcePointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        DataSource annotation = signature.getMethod().getAnnotation(DataSource.class);
        if (annotation == null) {
            DynamicDataSourceContextHolder.setDataSourceKey("primary");
        } else {
            DynamicDataSourceContextHolder.setDataSourceKey(annotation.value());
        }
        try {
            return point.proceed();
        } finally {
            DynamicDataSourceContextHolder.clearDataSourceKey();
        }
    }
}
6. 在您的Repository类中使用@DataSource注释来指定要使用的数据源。
 
public interface UserRepository extends JpaRepository<User, Long> {

    @DataSource("datasource1")
    @Query("select * from users")
    List<User> findAllFromDataSource1();

    @DataSource("datasource2")
    @Query("select * from users")
    List<User> findAllFromDataSource2();
}
现在,您可以在运行时动态选择要使用的数据库。要使用不同的数据库,请在访问数据库之前调用DynamicDataSourceContextHolder.setDataSourceKey(dataSourceKey)方法,并在访问数据库后调用DynamicDataSourceContextHolder.clearDataSourceKey()方法。
posted @   laolv  阅读(444)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示