SpringBoot教程(二十五) | SpringBoot配置多个数据源

server/2024/11/14 9:45:31/

SpringBoot教程(二十五) | SpringBoot配置多个数据源

  • 前言
  • 方式一:使用dynamic-datasource-spring-boot-starter
    • 引入maven依赖
    • 配置数据源
    • 动态切换数据源实战
  • 方式二:使用AbstractRoutingDataSource
    • 1. 创建数据源枚举类
    • 2. 创建数据源上下文持有者
    • 3. 创建自定义的 AbstractRoutingDataSource
    • 4. 配置yml文件
    • 5. 配置数据源
      • HikariCP 版本
      • Druid 版本
    • 6. 自定义多数据源切换注解
    • 7. 使用 AOP 或拦截器设置数据源键
    • 8. 在服务层 测试使用
    • 总结
  • 方式三:分包方式
    • 1. 添加依赖
    • 2. application.yml 配置文件
    • 3. DataSourceConfig1.java 配置类
    • 4. DataSourceConfig2.java 配置类
    • 5. Mapper接口和XML文件
    • 6. 使用Mapper接口的服务类
    • 总结

前言

SpringBoot配置多数据源指的是在一个Spring Boot项目中配置和连接到多个数据库实例的能力。
这种架构允许应用程序根据不同的业务需求、数据类型或性能要求,与多个独立的数据库环境交互。
在实现上,每个数据源都有自己的连接池、事务管理和数据访问对象。

方式一:使用dynamic-datasource-spring-boot-starter

引入maven依赖

Spring Boot 3 区别其他版本,使用的是dynamic-datasource-spring-boot3-starter ,
其他版本的 Spring Boot 使用 dynamic-datasource-spring-boot-starter , 除了依赖区别,其他配置和使用方式新老版本无差别。

Spring Boot 3

<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot3-starter</artifactId><version>4.2.0</version>
</dependency>

Spring 1.5.x 及 Spring 2.x.x

<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>4.2.0</version>
</dependency>

配置数据源

spring:datasource:dynamic:primary: master #设置默认的数据源或者数据源组,默认值即为 masterstrict: false # 设置严格模式,当数据源找不到时,是否抛出异常,默认为false不抛出datasource:master: # 主库type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置url: jdbc:mysql://www.youlai.tech:3306/youlai_boot?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=trueusername: youlaipassword: 123456slave: # 从库type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/youlai_boot?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=trueusername: rootpassword: 123456

动态切换数据源实战

注解切换数据源
@DS注解是 dynamic-datasource-spring-boot-starter提供的
@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解。

注解结果
没有@DS默认数据源
@DS(“dsName”)dsName可以为组名也可以为具体某个库的名称
java">/*** 主库查询*/
@DS("master")
@Select("select * from sys_user where id = #{userId}")
SysUser getUserFromMaster(Long userId);/*** 从库查询*/
@DS("slave")
@Select("select * from sys_user where id = #{userId}")
SysUser getUserFromSlave(Long userId);

单元测试类

java">package com.youlai.system.mapper;import com.youlai.system.model.entity.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
@Slf4j
class SysUserMapperTest {@Autowiredprivate SysUserMapper userMapper;private final Long userId = 1L;/*** 测试注解方式切换数据源*/@Testvoid testSwitchDataSourceByAnnotation() {SysUser masterUser = userMapper.getUserFromMaster(userId);log.info("用户ID:{} 主库姓名:{}", userId, masterUser.getNickname());SysUser slaveUser = userMapper.getUserFromSlave(userId);log.info("用户ID:{} 从库姓名:{}", userId, slaveUser.getNickname());}
}

测试结果

在这里插入图片描述

方式二:使用AbstractRoutingDataSource

AbstractRoutingDataSource 是 Spring 框架中用于实现多数据源路由的一个抽象类。
它允许你在运行时根据某种键(通常是线程本地变量)动态地选择数据源。

1. 创建数据源枚举类

java">/*** 数据源*/
public enum DataSourceType {/*** 数据源1* */DB1,/*** 数据源2* */DB2
}

2. 创建数据源上下文持有者

首先,你需要一个类来持有当前线程的数据源键(DataSource Type)。这通常是通过 ThreadLocal 实现的。

java">import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 数据源切换处理*/
public class DynamicDataSourceContextHolder {public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);/*** 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。*/private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();/*** 设置数据源的变量*/public static void setDataSourceType(String dsType) {log.info("切换到{}数据源", dsType);CONTEXT_HOLDER.set(dsType);}/*** 获得数据源的变量*/public static String getDataSourceType() {return CONTEXT_HOLDER.get();}/*** 清空数据源变量*/public static void clearDataSourceType() {CONTEXT_HOLDER.remove();}
}

3. 创建自定义的 AbstractRoutingDataSource

接下来,你需要扩展 AbstractRoutingDataSource 并重写 determineCurrentLookupKey 方法来返回当前线程的数据源键。

java">import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/*** Spring的AbstractRoutingDataSource抽象类,实现动态数据源(他的作用就是动态切换数据源)* AbstractRoutingDataSource中的抽象方法determineCurrentLookupKey是实现数据源的route的核心,* 这里对该方法进行Override。【上下文DynamicDataSourceContextHolder为一线程安全的ThreadLocal】*/
public class DynamicDataSource extends AbstractRoutingDataSource {/*** 取得当前使用哪个数据源* @return dbTypeEnum*/@Overrideprotected Object determineCurrentLookupKey() {return DynamicDataSourceContextHolder.getDataSourceType();}
}

4. 配置yml文件

spring:datasource:# 配置第一个数据源db1:url: jdbc:mysql://localhost:3306/db1username: user1password: pass1driver-class-name: com.mysql.cj.jdbc.Driver# 配置第二个数据源db2:url: jdbc:mysql://localhost:3306/db2username: user2password: pass2driver-class-name: com.mysql.cj.jdbc.Driver

5. 配置数据源

在你的配置类中,你需要配置多个数据源,并将它们添加到 multipleDataSource 中。

HikariCP 版本

java">import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.example.springbootfull.quartztest.datasource.DynamicDataSource;
import com.example.springbootfull.quartztest.enums.DataSourceType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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.core.io.Resource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;/*** 多数据源配置*/
@Configuration
public class DataSourceConfig {/*** 创建第一个数据源** @return dataSource*/@Bean(name = "dataSource1")@ConfigurationProperties(prefix = "spring.datasource.db1")public DataSource dataSource1() {return DataSourceBuilder.create().build();}/*** 创建第二个数据源** @return dataSource*/@Bean(name = "dataSource2")@ConfigurationProperties(prefix = "spring.datasource.db2")public DataSource dataSource2() {return DataSourceBuilder.create().build();}/*** 动态数据源配置* 多个相同类型的 Bean,那么就会出现歧义,需要使用@Qualifier* @Qualifier 是按名称来查找和注入 Bean 的* @return dataSource*/@Primary@Bean("multipleDataSource")public DataSource multipleDataSource(@Qualifier("dataSource1") DataSource db1,@Qualifier("dataSource2") DataSource db2) {DynamicDataSource dynamicDataSource = new DynamicDataSource();Map<Object, Object> dataSources = new HashMap<>();dataSources.put(DataSourceType.DB1, db1);dataSources.put(DataSourceType.DB2, db2);dynamicDataSource.setTargetDataSources(dataSources);//默认数据源dynamicDataSource.setDefaultTargetDataSource(db1);return dynamicDataSource;}@Bean("sqlSessionFactory")public SqlSessionFactory sqlSessionFactory(@Qualifier("multipleDataSource") DataSource multipleDataSource) throws Exception {// 导入mybatissqlsession配置MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();// 指明数据源sessionFactory.setDataSource(multipleDataSource);// 设置mapper.xml的位置路径Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/*.xml");sessionFactory.setMapperLocations(resources);//指明实体扫描(多个package用逗号或者分号分隔)//sessionFactory.setTypeAliasesPackage("com.szylt.projects.project.entity");// 导入mybatis配置MybatisConfiguration configuration = new MybatisConfiguration();configuration.setJdbcTypeForNull(JdbcType.NULL);configuration.setMapUnderscoreToCamelCase(true);configuration.setCacheEnabled(false);sessionFactory.setConfiguration(configuration);return sessionFactory.getObject();}//数据源事务配置@Beanpublic PlatformTransactionManager transactionManager(DataSource multipleDataSource) {return new DataSourceTransactionManager(multipleDataSource);}}

Druid 版本

需要先引入 Druid 依赖,这里使用的是 Druid 官方的 Starter

<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version>
</dependency>

然后,在properties配置文件中 为每个数据源配置DruidDataSour数据库连接池

spring.datasource.db1.type=com.alibaba.druid.pool.DruidDataSour
spring.datasource.db2.type=com.alibaba.druid.pool.DruidDataSour

接着把一下DataSourceConfig 类里面的 按下面的操作,就好了

  • DataSource 对象 换成 DruidDataSource 对象
  • DataSourceBuilder 对象 换成 DruidDataSourceBuilder 对象

6. 自定义多数据源切换注解

java">import com.example.springbootfull.quartztest.enums.DataSourceType;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义多数据源切换注解* 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource
{/*** 切换数据源名称* 默认为DB1*/public DataSourceType value() default DataSourceType.DB1;
}

7. 使用 AOP 或拦截器设置数据源键

为了在使用时能够动态地切换数据源,你需要在执行数据库操作之前设置数据源键。
这通常是通过 AOP(面向切面编程)或拦截器来实现的。

需要引入aop依赖

<!--spring切面aop依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

以下是一个使用 AOP 的示例:

以下这个位置,记得 替换成你项目中 自定义注解 DataSource 所在的具体位置
@Pointcut(“@annotation(com.example.xx.xx.DataSource) || @within(com.example.xx.xx.DataSource)”)

java">import java.util.Objects;import com.example.springbootfull.quartztest.annotation.DataSource;
import com.example.springbootfull.quartztest.datasource.DynamicDataSourceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;/*** 多数据源处理**/
@Aspect
@Order(1)
@Component
public class DataSourceAspect {protected Logger logger = LoggerFactory.getLogger(getClass());//此处替换成你项目中 自定义注解 DataSource 所在的具体位置@Pointcut("@annotation(com.example.xx.xx.DataSource)"+ "|| @within(com.example.xx.xx.DataSource)")public void dsPointCut() {}@Around("dsPointCut()")public Object around(ProceedingJoinPoint point) throws Throwable {DataSource dataSource = getDataSource(point);if (dataSource != null) {DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());}try {return point.proceed();} finally {// 销毁数据源 在执行方法之后DynamicDataSourceContextHolder.clearDataSourceType();}}/*** 获取需要切换的数据源*/public DataSource getDataSource(ProceedingJoinPoint point) {MethodSignature signature = (MethodSignature) point.getSignature();DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);if (Objects.nonNull(dataSource)) {return dataSource;}return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);}
}

8. 在服务层 测试使用

最后,在你的服务层方法上使用 @DataSource 注解来指定要使用的数据源。

java">import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class MyService {@Autowiredprivate MyMapper myMapper; // 假设MyMapper是一个Mapper接口// 使用第一个数据源@DataSource(value = DataSourceType.DB1)@Transactionalpublic void useDb1() {// 执行数据库操作myMapper.someMethod();}// 使用第二个数据源@DataSource(value = DataSourceType.DB2)@Transactionalpublic void useDb2() {// 执行数据库操作myMapper.anotherMethod();}
}

总结

通过上述步骤,你已经成功地在 Spring Boot 项目中配置了基于 AbstractRoutingDataSource 的多数据源支持。
当你调用服务层的方法时,AOP 拦截器会根据 @DataSource 注解的值设置当前线程的数据源键,从而动态地选择数据源。

方式三:分包方式

  1. 配置多个数据源:在Spring Boot的配置文件中(如application.propertiesapplication.yml),配置多个数据源的信息,包括URL、用户名、密码等。
  2. 创建数据源配置类:为每个数据源创建一个配置类,使用@Configuration注解标注,并在类中定义数据源(DataSource)、事务管理器(TransactionManager)以及SqlSessionFactory等Bean。
  3. 指定Mapper扫描路径:使用@MapperScan注解指定每个数据源对应的Mapper扫描路径,以便Spring Boot能够正确地加载和注册Mapper接口。

1. 添加依赖

首先,在pom.xml文件中添加必要的依赖,包括Spring Boot的Web启动器、MyBatis的Spring Boot启动器、数据库驱动等。例如:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>版本号</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 其他依赖 -->
</dependencies>

2. application.yml 配置文件

# Spring Boot应用程序的配置文件
spring:datasource:# 第一个数据源的配置db1:jdbc-url: jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8# 数据库用户名username: root# 数据库密码password: 123456# 数据库驱动类名driver-class-name: com.mysql.cj.jdbc.Driver# 第二个数据源的配置db2:jdbc-url: jdbc:mysql://localhost:3306/test2?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8username: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver

java__562">3. DataSourceConfig1.java 配置类

java">// 使用@Configuration注解表明这是一个配置类
@Configuration
// 使用@MapperScan注解指定Mapper接口所在的包,并指定SqlSessionFactory的引用
@MapperScan(basePackages = "com.example.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class DataSourceConfig1 {// 使用@Primary注解表明这是默认的数据源(如果有多个数据源时)// 使用@Bean注解表明这是一个Spring管理的bean,name属性指定bean的名称// 使用@ConfigurationProperties注解读取application.yml中的配置@Primary@Bean(name = "db1DataSource")@ConfigurationProperties(prefix = "spring.datasource.db1")public DataSource getDb1DataSource() {// 创建并返回数据源对象return DataSourceBuilder.create().build();}// 创建一个SqlSessionFactory对象,用于MyBatis的SQL会话管理@Primary@Bean(name = "db1SqlSessionFactory")public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();// 设置数据源sessionFactoryBean.setDataSource(dataSource);// 设置Mapper XML文件的位置sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/db1/*.xml"));// 返回SqlSessionFactory对象return sessionFactoryBean.getObject();}
}

java__597">4. DataSourceConfig2.java 配置类

这个类与DataSourceConfig1.java类似,但它是为第二个数据源配置的。

java">// 使用@Configuration注解表明这是一个配置类
@Configuration
// 使用@MapperScan注解指定第二个数据源对应的Mapper接口所在的包
@MapperScan(basePackages = "com.example.mapper.db2", sqlSessionFactoryRef = "db2SqlSessionFactory")
public class DataSourceConfig2 {// 创建一个名为db2DataSource的数据源bean@Bean(name = "db2DataSource")@ConfigurationProperties(prefix = "spring.datasource.db2")public DataSource getDb2DataSource() {// 创建并返回数据源对象return DataSourceBuilder.create().build();}// 创建一个名为db2SqlSessionFactory的SqlSessionFactory对象@Bean(name = "db2SqlSessionFactory")public SqlSessionFactory db2SqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();// 设置数据源sessionFactoryBean.setDataSource(dataSource);// 设置第二个数据源对应的Mapper XML文件的位置sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/db2/*.xml"));// 返回SqlSessionFactory对象return sessionFactoryBean.getObject();}
}

5. Mapper接口和XML文件

com.example.mapper.db1com.example.mapper.db2包下分别创建Mapper接口,这些接口定义了操作数据库的方法。
同时,在resources/mapper/db1resources/mapper/db2目录下创建对应的XML文件,这些文件包含了SQL语句和映射规则。

6. 使用Mapper接口的服务类

java">// 使用@Service注解表明这是一个服务类
@Service
public class MyService {// 注入第一个数据源的Mapper接口@Autowiredprivate Db1Mapper db1Mapper;// 注入第二个数据源的Mapper接口@Autowiredprivate Db2Mapper db2Mapper;// 使用第一个数据源的方法public void useDb1() {// 调用db1Mapper的方法执行数据库操作}// 使用第二个数据源的方法public void useDb2() {// 调用db2Mapper的方法执行数据库操作}
}

总结

通过上述配置,您可以在Spring Boot项目中配置多个数据源,并通过不同的Mapper接口来操作这些数据源。
每个数据源都有自己的配置类、数据源对象、SqlSessionFactory对象和Mapper接口。
这样,您就可以在同一个项目中方便地访问多个数据库了。

参考文章
【1】Spring Boot 3 整合 Mybatis-Plus 动态数据源实现多数据源切换


http://www.ppmy.cn/server/141580.html

相关文章

鸿蒙next版开发:ArkTS组件点击事件详解

在HarmonyOS 5.0中&#xff0c;ArkTS提供了一套完整的组件和事件处理机制&#xff0c;使得开发者能够创建交互性强的应用程序。本文将详细解读如何使用ArkTS组件处理点击事件&#xff0c;包括事件的注册、回调函数的编写以及事件对象的使用。 点击事件基础 点击事件是用户与应…

SQL面试题——奔驰面试题

SQL面试题——奔驰SQL面试题 我们的表大致如下 CREATE TABLE signal_log( vin STRING COMMENTvehicle frame id, signal_name STRING COMMENTfunction name, signal_value STRING COMMENT signal value , ts BIGINT COMMENTevent timestamp, dt STRING COMMENTformat yyyy-mm…

当使用key-value方式进行参数传递时,若key对应的是一个对象或数组结构,如何利用API Post工具进行模拟操作。

1. 后端服务代码如下 RequestMapping("/handle11")public Person handle11(Person person){System.out.println(person);return person;} 2. 后端入参结构 person是一个对象&#xff0c;对象结构如下&#xff1a; public class Person {private String username …

Mysql篇-Buffer Pool中的三大链表

为什么要有 Buffer Pool&#xff1f; 虽然说 MySQL 的数据是存储在磁盘里的&#xff0c;但是也不能每次都从磁盘里面读取数据&#xff0c;这样性能是极差的。 要想提升查询性能&#xff0c;那就加个缓存。所以&#xff0c;当数据从磁盘中取出后&#xff0c;缓存内存中&#xf…

EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?

在现代视频监控领域&#xff0c;跨区域的网络化视频监控管理平台成为了大中型项目的首选。EHOME视频平台EasyCVR以其强大的功能和兼容性&#xff0c;成为了众多项目的核心组件。它不仅能够管理视频资源、设备、用户、运维和安全&#xff0c;还支持多种行业标准协议&#xff0c;…

基于STM32设计的大棚育苗管理系统(4G+华为云IOT)_265

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】设计意义【5】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发1.5 参考文献1.6 系统框架图1.7 系统原理图1.8 实物图1.9…

三维测量与建模笔记 - 3 Python Opencv实现相机标定

import cv2 import numpy as np import glob import matplotlib.pyplot as pltcv2.__version__ #参考链接 #https://docs.opencv.org/3.4/dc/dbb/tutorial_py_calibration.html#相关参数 #设置寻找亚像素角点的参数&#xff0c;采用的停止准则是最大循环次数30和最大误差容限0.…

CondaError: Run ‘conda init‘ before ‘conda activate‘解决办法

已经执行了conda init&#xff0c;但是还是会报错CondaError: Run ‘conda init’ before ‘conda activate’ 原因&#xff1a;权限不够 解决办法&#xff1a;以管理员身份运行cmd&#xff0c;然后进入要操作的文件夹下&#xff0c;重新执行 conda init 和 conda activate 就可…