当前位置: 首页 > article >正文

缓存池和数据库连接池的使用(Java)

一、基本概念

1. 缓存池(待完善)

2. 数据库连接池(待完善)

二、代码实现

1. 场景描述:

使用ConcurrentHashMap和DruidDataSource 实现以下功能:

①从oracle主数据库的base_dataSource表中查询对应oracle数据库的连接串信息,如果连接池中没有该数据库的连接串信息,将该数据库连接串放入连接池中,下次再次请求该数据库时,先从连接池中获取该数据库信息。

②使用DruidDataSource管理数据库连接,来查询所有数据库的通用表Base_Person表中的数据。

2. 代码实现

2.1 添加依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.9</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.13</version>
</dependency>

2.2 配置文件配置主数据库信息

#oracle
spring.datasource.dynamic.primary=anita
spring.datasource.dynamic.datasource.anita.url=jdbc:oracle:thin:@oracle_url
spring.datasource.dynamic.datasource.anita.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.dynamic.datasource.anita.username=anita
spring.datasource.dynamic.datasource.anita.password=anitazxq

2.3 定义实体类

2.3.1 base_datasource实体类:DataSourceModel 
package com.example.dataSource.dto;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("base_datasource")
public class DataSourceModel {
    private String id;
    private String dbname;
    private String dbuser;
    private String dbpassword;
    private String dburl;
    private String dbdriver;
}
 2.3.2 base_person的实体类:BasePersonModel 
package com.example.dataSource.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BasePersonModel {
    private String id;
    private String name;
}

2.4 定义Mapper 

2.4.1 DataSourceModel对应的Mapper:DataSourceMapper 
package com.example.dataSource.mapper;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.dataSource.dto.DataSourceModel;
import org.apache.ibatis.annotations.Mapper;

@Mapper
@DS("anita")  //指定数据源
public interface DataSourceMapper extends BaseMapper<DataSourceModel> {
}
2.4.2  BasePersonModel 对应的Mapper:BasePersonMapper 
package com.example.dataSource.mapper;

import com.example.dataSource.dto.BasePersonModel;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface BasePersonMapper {
    @Select("SELECT * FROM base_person")
    List<BasePersonModel> getAllData();
}

2.5 定义Service层

根据dbName查询数据库连接信息

package com.example.dataSource.service;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.dataSource.dto.BasePersonModel;
import com.example.dataSource.dto.DataSourceModel;
import com.example.dataSource.mapper.BasePersonMapper;
import com.example.dataSource.mapper.DataSourceMapper;
import com.example.dataSource.utils.DataSourceCacheUtil;
import com.example.dataSource.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class DataOperateService {
    @Autowired
    private DataSourceMapper dataSourceMapper;
    //根据数据源名称查询数据库信息
    public DataSourceModel getDataSourceByDbName(String dbName)
    {
        QueryWrapper<DataSourceModel> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("dbname",dbName);
        DataSourceModel dataSource=dataSourceMapper.selectOne(queryWrapper);
        return dataSource;
    }
}

 2.6 数据库连接池

package com.example.dataSource.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.example.dataSource.dto.DataSourceModel;
import org.springframework.stereotype.Component;

@Component
public class DataSourceConnectionUtil {
    //创建数据库连接池
    public static DruidDataSource createDataSource(DataSourceModel dataSourceModel)
    {
        DruidDataSource dataSource=new DruidDataSource();

        dataSource.setDriverClassName(dataSourceModel.getDbdriver());
        dataSource.setUrl(dataSourceModel.getDburl());
        dataSource.setUsername(dataSourceModel.getDbuser());
        dataSource.setPassword(dataSourceModel.getDbpassword());

        dataSource.setValidationQuery("SELECT 1 FROM DUAL");//ORACLE验证查询
        dataSource.setTestWhileIdle(true);
        dataSource.setTestWhileIdle(false);
        dataSource.setTestOnReturn(false);

        //避免连接数一直增加
        dataSource.setKeepAlive(false);
        //设置keepAlive的时间间隔,单位毫秒
        dataSource.setKeepAliveBetweenTimeMillis(60000);
        dataSource.setTimeBetweenEvictionRunsMillis(50000);
        dataSource.setMinEvictableIdleTimeMillis(300000);
        dataSource.setMaxEvictableIdleTimeMillis(480000);
        dataSource.setBreakAfterAcquireFailure(true);
        dataSource.setConnectionErrorRetryAttempts(1);
        dataSource.setMinIdle(5);
        dataSource.setMaxActive(200);
        dataSource.setMaxWait(30000);
        return dataSource;
    }
}

2.7  缓存池

package com.example.dataSource.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.example.dataSource.dto.DataSourceModel;
import com.example.dataSource.service.DataOperateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;

@Component
public class DataSourceCacheUtil {
    @Autowired
    private DataOperateService dataOperateService;
    @Autowired
    private DataSourceConnectionUtil dataSourceConnectionUtil;
    private static final ConcurrentHashMap<String, DruidDataSource> dataSourceCache=new ConcurrentHashMap<>();

    //获取数据库连接
    public DruidDataSource getDataSource(String dbName)
    {
        //从缓存池中获取数据库信息
        DruidDataSource dataSource=dataSourceCache.get(dbName);
        if(dataSource==null)
        {
            DataSourceModel ds=dataOperateService.getDataSourceByDbName(dbName);
            //创建数据库连接池
            dataSource=dataSourceConnectionUtil.createDataSource(ds);
        }
        dataSourceCache.put(dbName,dataSource);
        return dataSource;
    }
    //在应用结束时关闭数据库连接池
    public void close()
    {
        for(DruidDataSource dataSource : dataSourceCache.values())
        {
            dataSource.close();
        }
    }
}

 2.8 创建SqlSessionFactory

初始化 MyBatis 所需的配置,并准备好一个可以用于数据库操作的 SqlSessionFactory 实例。通过这个工厂,应用程序可以方便地获取 SqlSession,从而进行数据库操作。

package com.example.dataSource.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.example.dataSource.mapper.BasePersonMapper;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import javax.sql.DataSource;

public class MyBatisUtil {
    public static SqlSessionFactory getSqlSessionFactory(DruidDataSource dataSource)
    {
        // 创建 MyBatis 配置
        Configuration configuration = new Configuration();
        configuration.setEnvironment(new Environment("development", new JdbcTransactionFactory(), dataSource));

        // 注册 Mapper
        configuration.addMapper(BasePersonMapper.class);

        // 返回 SqlSessionFactory
        return new SqlSessionFactoryBuilder().build(configuration);
    }
}

 2.9 从缓存池中获取目标数据库,查询数据。

在2.5的DataOperateService 类中添加方法,实现以下功能:从缓存池中找到目标数据源,切换数据源,查询该数据源中的base_person表。

    @Autowired
    private DataSourceCacheUtil dataSourceCacheUtil;
    public List<BasePersonModel> getData(String dbName)
    {
        DruidDataSource dataSource=dataSourceCacheUtil.getDataSource(dbName);
        SqlSessionFactory sqlSessionFactory= MyBatisUtil.getSqlSessionFactory(dataSource);
        // 获取 SqlSession
        try(SqlSession sqlSession = sqlSessionFactory.openSession()){
            // 获取 Mapper
            BasePersonMapper basePersonMapper=sqlSession.getMapper(BasePersonMapper.class);
            //查询
            List<BasePersonModel> data=basePersonMapper.getAllData();
            return data;
        }
        catch (Exception e) {
            // 记录异常或抛出自定义异常
            e.printStackTrace();
            // 这里可以根据需要返回空列表或重新抛出异常
            return Collections.emptyList();
        }

    }

2.10 通过接口将上述功能进行串联‘

package com.example.dataSource.controller;

import com.example.dataSource.dto.BasePersonModel;
import com.example.dataSource.service.DataOperateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/differentDSUse")
public class DataOperation {

    @Autowired
    DataOperateService dataOperateService;

    @GetMapping("/search")
    public List<BasePersonModel> get()
    {
        return dataOperateService.getData("test");
    }
}

3. 使用到的java包解析:

 待完善


http://www.kler.cn/a/325796.html

相关文章:

  • 退款成功订阅消息点击后提示订单不存在
  • ASP.NET Core Webapi 返回数据的三种方式
  • Visual Studio 圈复杂度评估
  • leetcode-44-通配符匹配
  • 第6章详细设计 -6.7 PCB工程需求表单
  • 号卡分销系统,号卡系统,物联网卡系统源码安装教程
  • Vue 中自定义指令的探索与实践
  • ZYNQ:点亮LED灯
  • 每天一个数据分析题(四百七十六)- 线性回归建模
  • Go语言匿名字段使用与注意事项
  • Markdown 字体颜色
  • postgreSql常用操作
  • Spring Boot 多线程事务管理:使用 CyclicBarrier 和 PlatformTransactionManager 实现全局事务控制
  • Docker-3.启动
  • Vue3+FastAPI中Token的刷新机制(含代码示例)
  • 鸿蒙HarmonyOS之选择相册文件(照片/视频)方法
  • MySQL之分库分表后带来的“副作用”你是怎么解决的?
  • Servlet 3.0新特征
  • 新能源汽车储充机器人:能源高效与智能调度
  • 【2024.9.29练习】R 格式
  • P9241 [蓝桥杯 2023 省 B] 飞机降落
  • 【MySQL】查询原理 —— B+树查询数据全过程
  • docker安装Portainer CE
  • 华为eNSP:端口隔离
  • 【AI大模型】Prompt Engineering
  • tr命令:替换文本中的字符