如何在Spring/SpringBoot项目启动后,动态修改数据库连接

先说结论:

在项目启动后,使用修改配置文件+restart()连接/连接池对象的方法解决。

 

-----------------------------------------------------

思路2:

使用读写锁,给restart()、setUrl()等代码块加写锁;

给数据库操作方法加读锁。

这样就可以在修改数据库连接信息时,先获取写锁,保证数据库操作方法不能执行(如果修改到一半,有数据库操作方法执行的话,后续修改链接方法会报错,所以不能让数据库操作方法执行);

而在不修改连接时,数据库操作方法之间获取的是读锁,不会影响线程彼此之间的操作。

 

具体方法:

1.读写锁用法:

//公平读写锁
//ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
//非公平读写锁,默认false
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
//读锁
lock.readLock().lock();

//...
//省略数据库增删改查方法

//执行完后,释放读锁
lock.readLock().unlock();


/*-----------------------------------*/

//Druid数据库连接池,注意对象类型是 DruidDataSource
//@Autowired
//DruidDataSource dataSource;

//写锁
lock.writeLock().lock();

//修改数据库连接信息
dataSource.restart();
dataSource.setUrl("数据库url");
dataSource.setUserName("数据库用户名");
dataSource.setPassword("数据库密码");
dataSource.setDriverClassName("数据库驱动名称");

//执行完后,释放写锁
lock.writeLock().unlock();

2.使用AOP,切入调用数据库的mapper方法,调用前加读锁,调用后释放读锁;

3.对修改数据库连接的操作加写锁,修改完成后释放写锁。

 

-----------------------------------------------------

 

之前听同事说,有一个需求,要求在spring/springboot项目启动后,留一个接口,修改数据库连接。

意思就是项目启动后,本来我查的某一个数据库;然后突然要改为查询另一个数据库,怎么办。

可能主备库会用到?当主库挂了后,要在不影响项目运行的情况下改为查备库?

然后本人稍微研究了一下,把代码与思路放在下面。

 

-----------------------------------------------------

 

1.首先,spring/springboot项目可以使用druid链接池。

springboot下需要使用的jar包:
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

spring下需要使用的jar包:
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.1</version>
</dependency>

 

2.然后,配置好druid连接池,把它交给spring容器管理。

 

3.在代码中,使用注解把druid连接池对象注入,例如:

@Autowired 
DruidDataSource dataSource;

 

4.然后,就可以使用这个连接池对象修改链接信息了。需要先执行restart(),然后用set方法修改,然后修改后的链接信息就生效了,例如:

//注入Druid数据库连接池对象
@Autowired
DruidDataSource dataSource;

//注入一个测试用的mapper
@Autowired
UserMapper userMapper;


public void test(){
  //先查回一个用户名来,证明现在链接没有修改。(用的是启动spring时配置的链接信息)
  String username = userMapper.getUserNameById(1);
  System.out.println(username);
  
  //先执行restart(),然后才能执行set,否则会报错UnsupportedOperationException()
  dataSource.restart();
  
  //然后就能修改链接信息了
  //填写一个不存在的数据库,测试用
  dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/nobase?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true");
  //dataSource.setDriver("这里填驱动对象");
  //dataSource.setUsername("这里填用户名");
  //dataSource.setPassword("这里填密码");

  //然后再调用下mapper,此时会报错,因为本人将链接信息修改了,对应一个不存在的数据库,当然会报错
  String username = userMapper.getUserNameById(1);
  System.out.println(username);
}

注意事项:

1.需要先执行restart(),然后才能执行set,否则会报错UnsupportedOperationException()

2.在高并发场景下,需要做些限制才能使用,例如以下情况,执行set时,也会报错UnsupportedOperationException()

public void test(){
  String username = userMapper.getUserNameById(1);
  System.out.println(username);
  
  dataSource.restart();

  //如果执行restart后,有程序执行了mapper,则下方会报错
  String username = userMapper.getUserNameById(1);
  System.out.println(username);
 
  //由于上方执行了mapper,导致dataSource被init,所以这里会报错;详情见源码
  //执行set时必须在dataSource刚restart后才行(此时还没有被init)
  dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/nobase?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true");
 
  String username = userMapper.getUserNameById(1);
  System.out.println(username);
}

原理就是,dataSource执行setUrl等方法时,源码会判断DataSource是否已经被初始化(init);如果已经被初始化,则报错UnsupportedOperationException();

dataSource执行restart()方法后,会处于未被初始化的状态,所以才能执行setUrl等操作;

而当dataSource执行restart()方法后,执行mapper等数据库操作时,会被初始化(init);

接着想执行setUrl等方法,会发现dataSource被初始化了,然后报错,导致修改链接失败。

 

=======================================================

controller中注入DruidDataSource报错的,可以试下下面这个:

https://blog.csdn.net/zhu0836/article/details/84330666

=======================================================

正确解决方法

1.由于数据库连接初始化时一般读取的是配置文件(假如数据库连接url与用户名密码在config.properties中保存),所以启动项目时,让项目读取外部的配置文件;

2.项目启动后,可以先把配置文件中的数据库连接信息修改掉(config.properties),手动修改或写个Controller进行修改都可;

3.然后再写个Controller,其中调用一下dataSource.restart()就可以了;之后有线程执行数据库操作时,dataSource自动重新初始化,读取修改后的配置文件,就实现项目启动后修改数据库连接的效果了。

  • 6
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
要在IDEA 2021创建一个Spring Boot项目并连接数据库,你需要按照以下步骤进行操作: 1. 首先,在你的pom.xml文件添加数据库依赖。这包括mysql-connector-java和spring-boot-starter-jdbc。你可以在<dependencies>标签添加以下代码来引入这些依赖项: ``` <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> ``` 2. 接下来,在application.yml文件配置数据库连接信息。你可以根据你的实际情况修改以下配置: ``` spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/your-database-name username: your-username password: your-password ``` 请确保将"your-database-name"替换为你的数据库名称,"your-username"替换为你的数据库用户名,"your-password"替换为你的数据库密码。如果密码是纯数字,请使用双引号将其括起来。 3. 确保你已经创建了数据库并导入了相应的数据库文件。 4. 导入项目到IDEA,并选择在本地maven仓库导入所需的依赖项。 5. 检查并选择正确的JDK版本。Spring Boot项目通常需要使用JDK 11。 6. 启动项目,确保所有六个服务都已启动。 通过按照以上步骤操作,你就可以在IDEA 2021创建Spring Boot项目并连接数据库了。请确保按照实际情况修改相应的配置信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [使用idea工具创建springboot项目,连接mysql数据库书写简单接口](https://blog.csdn.net/ymeddmn/article/details/95992463)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [idea怎么创建SpringBoot项目以及连接数据库的配置](https://blog.csdn.net/m0_54181890/article/details/125877205)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [系统基于springboot框架,使用Java+vue编写,为前后端分离的微服务项目](https://download.csdn.net/download/Abelon/88250447)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追逐梦想永不停

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值