Spring 多数据源方法级别注解实现

这篇具有很好参考价值的文章主要介绍了Spring 多数据源方法级别注解实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring框架提供了多种数据源管理方式,其中多数据源管理是其中之一。多数据源管理允许应用程序使用多个数据源,而不是只使用一个数据源,从而提高了应用程序的灵活性和可靠性。

多数据源管理的主要目的是让应用程序能够在不同的数据库之间切换,以满足不同的业务需求。例如,如果应用程序需要访问一个高可用性的数据库,但是该数据库当前不可用,那么应用程序可以自动切换到备用数据库,以保证业务的连续性。

在多数据源管理中,Spring框架通过使用JNDI(Java命名和目录接口)来管理数据源。JNDI允许应用程序在运行时动态查找数据源,并且可以使用不同的数据源来访问不同的数据库。

在多数据源管理中,还需要考虑数据源的配置和管理。这包括创建数据源、配置数据源、管理连接池和处理连接泄漏等问题。Spring框架提供了多种数据源配置和管理的工具和技术,例如Spring JDBC Template、Spring Data JPA和Spring Boot等。

总之,多数据源管理是Spring框架中非常重要的一部分,它可以提高应用程序的灵活性和可靠性,从而更好地满足业务需求。

废话少说,直接开干!

下面详细地介绍一下多数据源的实现过程,同时实现一个方法级别的注解,便于灵活使用。

1, Pom配置

引入mysql,spring-boot-starter-jdbc

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
	<version>2.4.2</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>${mysql-connector.version}</version>
</dependency>
<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>${mybatis-plus.version}</version>
</dependency>

2,配置数据源

可以在项目里,或者在apollo,nacos等配置中心上

#数据源master
spring.dynamic.datasource.master.url = jdbc:mysql://127.0.0.1:3306/aaa?characterEncoding=utf-8&rewriteBatchedStatements=true&tinyInt1isBit=false&allowMultiQueries=true
spring.dynamic.datasource.master.username = root
spring.dynamic.datasource.master.password = xxxxxxxx
spring.dynamic.datasource.master.driver-class-name = com.mysql.cj.jdbc.Driver
spring.dynamic.datasource.master.type = com.zaxxer.hikari.HikariDataSource

#数据源slave
spring.dynamic.datasource.slave.url = jdbc:mysql://127.0.0.1:3306/bbb?characterEncoding=utf-8&rewriteBatchedStatements=true&tinyInt1isBit=false&allowMultiQueries=true
spring.dynamic.datasource.slave.username = root
spring.dynamic.datasource.slave.password = yyyyyyyy
spring.dynamic.datasource.slave.driver-class-name = com.mysql.cj.jdbc.Driver
spring.dynamic.datasource.slave.type = com.zaxxer.hikari.HikariDataSource

3,读取数据源配置

3.1 先看整个项目结构

Spring 多数据源方法级别注解实现,微服务&amp;技术中台,spring,数据库,oracle,多数据源,注解

3.2 新增读取数据源配置类
import lombok.Data;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Map;

@Data
@ConfigurationProperties(prefix = "spring.dynamic")
public class DSProperties {
    private Map<String, DataSourceProperties> datasource;
}
 3.3 新增线程和数据源mapping的类

import com.xxx.gateway.common.Constant;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DynamicDataSourceHolder {
    /**
     * 保存动态数据源名称
     */
    private static final ThreadLocal<String> DYNAMIC_DATASOURCE_KEY = new ThreadLocal<>();

    /**
     * 设置/切换数据源,决定当前线程使用哪个数据源
     */
    public static void setDynamicDataSourceKey(String key){
        log.info("数据源切换为:{}",key);
        DYNAMIC_DATASOURCE_KEY.set(key);
    }

    /**
     * 获取动态数据源名称,默认使用mater数据源
     */
    public static String getDynamicDataSourceKey(){
        String key = DYNAMIC_DATASOURCE_KEY.get();
        return key == null ? Constant.MASTER_DATASOURCE : key;
    }

    /**
     * 移除当前数据源
     */
    public static void removeDynamicDataSourceKey(){
        log.info("移除数据源:{}",DYNAMIC_DATASOURCE_KEY.get());
        DYNAMIC_DATASOURCE_KEY.remove();
    }
}
3.4 继承路由多数据源的抽象类,并实现determineCurrentLookupKey方法
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        String dataBaseType = DynamicDataSourceHolder.getDynamicDataSourceKey();
        return dataBaseType;
    }
}

4,根据配置重写数据源和事务管理器

注意: 下面这个注解里的basePackages是你项目的路径

@MapperScan(basePackages = {"com.xxx.gateway.mapper"},
sqlSessionFactoryRef = "SqlSessionFactory")


import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableConfigurationProperties(DSProperties.class)
@MapperScan(basePackages = {"com.xxx.gateway.mapper"},
        sqlSessionFactoryRef = "SqlSessionFactory")
public class DynamicDataSourceConfig {

    @Bean(name = "dynamicDataSource")
    public DynamicDataSource DataSource(DSProperties dsProperties) {
        Map targetDataSource = new HashMap<>(8);
        dsProperties.getDatasource().forEach((k, v) -> {
            targetDataSource.put(k, v.initializeDataSourceBuilder().build());
        });
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSource);
        return dataSource;
    }

    /**
     * 创建动态数据源的SqlSessionFactory,传入的是动态数据源
     * @Primary这个注解很重要,如果项目中存在多个SqlSessionFactory,这个注解一定要加上
     */
    @Primary
    @Bean("SqlSessionFactory")
    public SqlSessionFactory sqlSessionFactoryBean(DynamicDataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setDefaultFetchSize(100);
        configuration.setDefaultStatementTimeout(30);
        sqlSessionFactoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
        sqlSessionFactoryBean.setConfiguration(configuration);
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 重写事务管理器,管理动态数据源
     */
    @Primary
    @Bean(value = "transactionManager")
    public PlatformTransactionManager annotationDrivenTransactionManager(DynamicDataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

5,注解实现

5.1 新增注解定义 
import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DS {
    String value() default Constant.MASTER_DATASOURCE;
}

Spring 多数据源方法级别注解实现,微服务&amp;技术中台,spring,数据库,oracle,多数据源,注解

5.2 新增注解实现
import com.xxx.gateway.config.DynamicDataSourceHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Objects;

@Aspect
@Order(1)
@Component
@Slf4j
public class DsAspect {
    @Pointcut("@annotation(com.xgd.gateway.aspect.DS)")
    public void dsPointCut() {
    }

    //环绕通知
    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        String key = getDefineAnnotation(joinPoint).value();
        DynamicDataSourceHolder.setDynamicDataSourceKey(key);
        try {
            return joinPoint.proceed();
        } finally {
            DynamicDataSourceHolder.removeDynamicDataSourceKey();
        }
    }

    /**
     * 先判断方法的注解,后判断类的注解,以方法的注解为准
     * @param joinPoint
     * @return
     */
    private DS getDefineAnnotation(ProceedingJoinPoint joinPoint){
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        DS dataSourceAnnotation = methodSignature.getMethod().getAnnotation(DS.class);
        if (Objects.nonNull(methodSignature)) {
            return dataSourceAnnotation;
        } else {
            Class<?> dsClass = joinPoint.getTarget().getClass();
            return dsClass.getAnnotation(DS.class);
        }
    }
}

6, 通过注解使用多数据源

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xxx.gateway.aspect.DS;
import com.xxx.gateway.domain.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper extends BaseMapper<User> {
    public User queryByCode(@Param("code") String code);

    @DS(value="master")
    public User queryByCodeNoPass(@Param("code") String code);

    @DS(value="slave1")
    public List<String> queryBanks();
}

注意:

1,@DS注解里的value值是可以随意的,只要和配置中心里spring.dynamic.datasource.后面的一致就可以。

Spring 多数据源方法级别注解实现,微服务&amp;技术中台,spring,数据库,oracle,多数据源,注解

 2,如果方法上没有配置数据源,那么就是走默认的master数据源,所以项目里必须至少配置了master数据源。

3,各个数据源可以重复,因为不会校验是否重复。

码字不易,记得点赞哟文章来源地址https://www.toymoban.com/news/detail-606929.html

到了这里,关于Spring 多数据源方法级别注解实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot通过自定义注解实现多数据源

    ✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: Java从入门到精通 ✨特色专栏: MySQL学习 🥭本文内容:SpringBoot通过自定义注解实现多数据源 📚个人知识库: Leo知识库,欢迎大家访问 大家好

    2024年02月03日
    浏览(37)
  • SpringBoot+MyBatis-Plus多数据源@DS注解失效的解决方法

    引入 dynamic-datasource: application.yml 数据源配置: 详细使用请看 MyBatis-Plus官网 这种场景还是比较常见,比如在一个为master数据源的调用slave数据源就会失效 slave数据源Service方法 mater数据源Service方法调用slave数据源Service方法 这里会出现没有走slave_1,依然还是master数据源 需要在

    2024年01月18日
    浏览(43)
  • SpringBoot @DS注解实现多数据源配置及问题解决

    进过验证,@DS注解加到mapper接口、service接口、service方法里都不生效,获取的还是默认的主数据源。猜测是由于spring的aop切面机制导致拦截不到@DS注解,进而不能切换数据源,正确的做法是添加到service实现类或者实现类里具体的方法上。 在事务方法内调用@DS注解的方法,@D

    2023年04月25日
    浏览(23)
  • 基于注解切换、Hikari实现的SpringBoot动态数据源(支持JNDI)

    先说效果,要实现方法级别注解切换当前数据源,不设置注解时走默认数据源,同时支持JNDI源。 Spring框架中存在一个抽象类 AbstractRoutingDataSource ,他是一个可以动态选择当前DataSource的路由类,我们就是要从这里入手,重新实现数据源的切换选择逻辑。然后借助注解和切面,

    2024年02月08日
    浏览(68)
  • springboot整合多数据源的配置以及动态切换数据源,注解切换数据源

    在许多应用程序中,可能需要使用多个数据库或数据源来处理不同的业务需求。Spring Boot提供了简便的方式来配置和使用多数据源,使开发人员能够轻松处理多个数据库连接。如果你的项目中可能需要随时切换数据源的话,那我这篇文章可能能帮助到你 ℹ️:这里对于pom文件

    2024年02月10日
    浏览(42)
  • Spring | 基于SpringBoot的多数据源实战 - 使用seata实现多数据源的全局事务管理

    在软件开发中, 多数据源 的应用越来越普遍,特别是在 微服务架构 和 业务模块化 的场景下。多数据源能够让不同的业务模块和微服务拥有各自独立的数据存储,大大提高了系统的灵活性和可维护性。本文将深入探讨多数据源的配置和实施,以及在 Spring Boot 环境下,如何通

    2024年02月07日
    浏览(50)
  • spring多数据源动态切换的实现原理及读写分离的应用

    AbstractRoutingDataSource 是Spring框架中的一个抽象类,可以实现多数据源的动态切换和路由,以满足复杂的业务需求和提高系统的性能、可扩展性、灵活性。 多租户支持:对于多租户的应用,根据当前租户来选择其对应的数据源,实现租户级别的隔离和数据存储。 分库分表:为了

    2024年02月14日
    浏览(29)
  • 若依分离版——配置多数据源(mysql和oracle),实现一个方法操作多个数据源

    目录 一、若依平台配置           二、编写oracle数据库访问的各类文件  三.  一个方法操作多个数据源 一、若依平台配置 1、在ruoyi-admin的pom.xml添加oracle依赖 2、引入ojdbc6.jar包 在ruoyi-admin的resource下创建lib文件夹,将ojdbc6.jar包保存在此目录下 3.  刷新maven 刷新maven保证ruo

    2024年02月05日
    浏览(32)
  • 如何在Spring Boot应用中使用Nacos实现动态更新数据源

    🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础入门篇)》学会Golang语言

    2024年02月10日
    浏览(28)
  • Spring Boot集成Druid实现多数据源的两种方式

    目录 项目场景: 一、集成com.baomidou的方式 1、maven依赖: 2、 配置文件: 3、 使用注解切换数据源:  二、基于AOP手动实现多数据源原生的方式 1、maven依赖: 2、 配置文件: 3、 多数据源名称类 4、自定义注解  5、配置类 6、动态数据源配置  7、AOP切面拦截注解 8、Dao层,

    2024年02月09日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包