spring多数据源如何切换

fiy 其他 17

回复

共3条回复 我来回复
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    Spring框架提供了多种方式来实现多数据源切换。下面我将介绍几种常用的方法。

    1. 使用注解切换数据源:
      可以使用Spring提供的@Primary注解,标记默认数据源,然后使用@Qualifier注解指定具体的数据源。
    @Configuration
    public class DataSourceConfig {
        
        @Bean
        @Primary
        @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();
        }
    
        @Bean
        @Primary
        public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
            return new JdbcTemplate(primaryDataSource);
        }
    
        @Bean
        public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
            return new JdbcTemplate(secondaryDataSource);
        }
    }
    

    在application.properties(或application.yml)文件中配置数据源信息:

    spring.datasource.primary.url=jdbc:mysql://localhost:3306/primarydb
    spring.datasource.primary.username=root
    spring.datasource.primary.password=123456
    
    spring.datasource.secondary.url=jdbc:mysql://localhost:3306/secondarydb
    spring.datasource.secondary.username=root
    spring.datasource.secondary.password=123456
    
    1. 使用AOP切换数据源:
      通过AOP技术,在方法执行前动态切换数据源。

    首先定义一个注解,用于标记需要切换数据源的方法:

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DataSource {
        String value() default "primary";  // 默认数据源为primary
    }
    

    然后定义一个切面,通过@Around注解来拦截被@DataSource注解标记的方法,并根据注解的值来切换数据源:

    @Aspect
    @Component
    public class DataSourceAspect {
    
        @Around("@annotation(dataSourceAnnotation)")
        public Object around(ProceedingJoinPoint joinPoint, DataSource dataSourceAnnotation) throws Throwable {
            String dataSourceName = dataSourceAnnotation.value();
            DataSourceContextHolder.setDataSource(dataSourceName);
    
            try {
                return joinPoint.proceed();
            } finally {
                DataSourceContextHolder.clearDataSource();
            }
        }
    }
    

    在需要切换数据源的方法上添加@DataSource注解:

    @Service
    public class UserService {
        
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @DataSource("primary")
        public void addUser(User user) {
            jdbcTemplate.update("INSERT INTO user(name, age) VALUES(?, ?)", user.getName(), user.getAge());
        }
    
        @DataSource("secondary")
        public void updateUser(User user) {
            jdbcTemplate.update("UPDATE user SET age = ? WHERE name = ?", user.getAge(), user.getName());
        }
    }
    
    1. 使用RoutingDataSource切换数据源:
      Spring提供了一个抽象的RoutingDataSource类来动态切换数据源。我们可以继承该类,重写determineCurrentLookupKey()方法来决定当前使用的数据源。

    首先定义一个枚举类,用于表示数据源的key:

    public enum DataSourceKey {
        PRIMARY, SECONDARY;
    }
    

    然后定义一个RoutingDataSource类,重写determineCurrentLookupKey()方法:

    public class MyRoutingDataSource extends AbstractRoutingDataSource {
        
        @Override
        protected Object determineCurrentLookupKey() {
            return DataSourceContextHolder.getDataSource();
        }
    }
    

    在Spring配置文件中配置数据源和RoutingDataSource:

    <bean id="primaryDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/primarydb"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    
    <bean id="secondaryDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/secondarydb"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    
    <bean id="routingDataSource" class="com.example.MyRoutingDataSource">
        <property name="defaultTargetDataSource" ref="primaryDataSource"/>
        <property name="targetDataSources">
            <map>
                <entry key="PRIMARY" value-ref="primaryDataSource"/>
                <entry key="SECONDARY" value-ref="secondaryDataSource"/>
            </map>
        </property>
    </bean>
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="routingDataSource"/>
    </bean>
    

    最后,在需要切换数据源的地方设置当前使用的数据源:

    DataSourceContextHolder.setDataSource(DataSourceKey.PRIMARY);
    jdbcTemplate.update("INSERT INTO user(name, age) VALUES(?, ?)", user.getName(), user.getAge());
    
    DataSourceContextHolder.setDataSource(DataSourceKey.SECONDARY);
    int count = jdbcTemplate.update("UPDATE user SET age = ? WHERE name = ?", user.getAge(), user.getName());
    

    总结:
    无论是使用注解、AOP还是RoutingDataSource来实现多数据源切换,都为我们提供了灵活的选择。根据项目需求和个人喜好来选择合适的方法即可。希望以上介绍对你有所帮助。

    1年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    Spring框架提供了多种方式来实现多数据源切换,以下是其中的几种常见方式:

    1. 配置多个数据源:
      在Spring的配置文件中,可以配置多个数据源,每个数据源都有自己的连接信息和配置。可以使用@Configuration注解或XML文件来配置。然后使用@Primary注解指定默认的数据源,通过@Qualifier注解指定使用哪个数据源进行操作。

    2. 使用RoutingDataSource:
      RoutingDataSource是Spring提供的一个特殊的数据源,它可以根据配置或程序动态地选择不同的数据源。可以通过继承AbstractRoutingDataSource类来实现自己的RoutingDataSource,重写determineCurrentLookupKey()方法来决定使用哪个数据源。

    3. 使用AOP切面:
      可以使用Spring框架的AOP功能,通过定义切面和切点,实现在每个数据源操作前切换数据源的功能。可以使用@Before注解或XML配置,通过切面方法中切换数据源。

    4. 使用多个JdbcTemplate:
      JdbcTemplate是Spring提供的访问数据库的工具类,可以通过创建多个JdbcTemplate对象,每个对象使用不同的数据源,来实现多数据源切换。可以使用@Autowired注解将多个JdbcTemplate注入到相应的类中,然后在需要切换数据源的地方使用具体的JdbcTemplate。

    5. 使用动态代理:
      可以使用Java的动态代理来代理每个数据源的实现类,在代理方法中切换数据源。通过使用Proxy类和InvocationHandler接口来实现动态代理,动态代理的实现方式有多种,可以根据具体需求选择适合的方式。

    需要注意的是,在使用多数据源时,需要保证每个数据源的连接信息和配置正确,并且在切换数据源时,要确保事务的正确性和一致性。此外,在多数据源的情况下,还需要考虑缓存的管理、数据库连接池的配置和性能优化等问题。

    1年前 0条评论
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    在Spring框架中,使用多数据源是非常常见的需求。利用多数据源可以让我们在一个应用程序中访问多个不同的数据库或数据源。下面我将介绍几种常见的切换多数据源的方式:

    1. 使用AbstractRoutingDataSource类:Spring为多数据源提供了AbstractRoutingDataSource抽象类,我们可以继承这个类并实现其determineCurrentLookupKey()方法来动态切换数据源。

    首先,定义一个继承AbstractRoutingDataSource的类,例如DynamicDataSource,然后重写determineCurrentLookupKey()方法,在该方法中根据一定的规则选择当前的数据源的key。可以通过ThreadLocal或者使用其他方式来存放当前所选择的key。最后,在Spring的配置文件中配置DynamicDataSource作为主数据源。

    例如,我们可以通过使用ThreadLocal来实现数据源的动态切换。创建一个DynamicDataSource类继承AbstractRoutingDataSource,并实现determineCurrentLookupKey()方法。在该方法中,我们可以从ThreadLocal中获取当前线程的数据源的key。

    public class DynamicDataSource extends AbstractRoutingDataSource {
    
        @Override
        protected Object determineCurrentLookupKey() {
            return DataSourceContextHolder.getDataSourceKey();
        }
    }
    

    然后,在配置文件中配置DynamicDataSource作为主数据源,并配置多个数据源。同时,我们还需要创建一个DataSourceContextHolder类来存放当前线程的数据源的key。

    public class DataSourceContextHolder {
    
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    
        public static void setDataSourceKey(String dataSourceKey) {
            contextHolder.set(dataSourceKey);
        }
    
        public static String getDataSourceKey() {
            return contextHolder.get();
        }
    
        public static void clearDataSourceKey() {
            contextHolder.remove();
        }
    }
    
    1. 使用AOP切面:另一种常见的方式是使用AOP切面来实现多数据源切换。我们可以使用Spring框架的AOP功能,在数据访问层的方法执行之前,通过AOP切面来动态切换数据源。

    首先,在Spring的配置文件中配置多个数据源,并配置AOP切面。在切面中,通过方法的注解或者其他方式来判断当前需要切换的数据源,并通过AOP提供的Around通知来切换数据源。

    @Aspect
    @Component
    public class DataSourceAspect {
    
        @Around("@annotation(dataSource)")
        public Object switchDataSource(ProceedingJoinPoint point, DataSource dataSource) throws Throwable {
            try {
                DataSourceContextHolder.setDataSourceKey(dataSource.value());
                return point.proceed();
            } finally {
                DataSourceContextHolder.clearDataSourceKey();
            }
        }
    }
    
    1. 使用注解:还可以使用注解的方式来切换数据源。通过在需要访问的方法上添加注解,在注解中指定当前方法需要使用的数据源。

    首先,定义一个注解类,例如@DataSource,并在该注解中定义一个value属性,用于指定对应的数据源的key。然后,创建一个切面类,并在切面类中处理所有被@DataSource注解所标记的方法,在该方法中切换数据源。

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DataSource {
        String value() default "default";
    }
    
    @Aspect
    @Component
    public class DataSourceAspect {
    
        @Around("@annotation(dataSource)")
        public Object switchDataSource(ProceedingJoinPoint point, DataSource dataSource) throws Throwable {
            try {
                DataSourceContextHolder.setDataSourceKey(dataSource.value());
                return point.proceed();
            } finally {
                DataSourceContextHolder.clearDataSourceKey();
            }
        }
    }
    

    以上是几种常见的切换多数据源的方式。根据具体的需求和项目结构,选择合适的方式来切换数据源,以实现多数据源的访问。

    1年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部