ToB企服应用市场:ToB评测及商务社交产业平台

标题: 缓存池和数据库连接池的使用(Java) [打印本页]

作者: 万万哇    时间: 2024-10-3 15:00
标题: 缓存池和数据库连接池的使用(Java)
一、根本概念


   缓存池机制主要用于存储和管理经常访问的数据,以进步应用的性能和相应速率。它通过将计算的数据或着将数据库查询的效果缓存起来,淘汰重复计算和数据重新获取,从而进步效率。
  1. 根本概念
  缓存池是一种临时存储空间,用于生存数据的副本,这些副本可以是计算效果、数据库查询效果或其他必要频繁访问的数据。当必要数据时,起首检查缓存,如果缓存中存在,则直接使用;否则,从原始数据源获取并将其存入缓存。
  2. 缓存的类型
  
  3. 使用思量:
  
  4. 缓存池与进程、线程的关系
  4.1 进程中的缓存池:
  
  4.2 线程中的缓存池:
  
  
   数据库连接池是用来管理数据库连接的工具,尤其对于高并发的环境,使用连接池可以避免频繁创建和关闭数据库连接,淘汰资源斲丧。
  1. 根本概念
  
  2. 工作原理
  
  3. 常见参数配置:
  
  二、代码实现

1. 场景形貌:

   1. 场景形貌:
          现有一个主系统,该主系统下有多个子系统,主系统可以连接所有子系统的数据库(主系统的数据表base_datasource中存着所有子系统的数据库信息),查询这些子系统的用户信息(用户信息表:base_person)。
  2. 实现以下功能:
          主系统步伐要连接某个子系统的数据库查询用户信息,步伐先从缓存池中获取数据库信息,如果缓存池中没有,则从数据库中查询该子系统的数据库信息,创建一个连接池,将其添加到缓存池中,最后连接该数据库查询数据。
  2. 该功能的实现用到的工具类

2.1 ConcurrentHashMap(缓存池)

   ConcurrentHashMap是Java中用于高效并发访问的哈希表实现,它允许多个线程同时读取和写入数据,而不会导致数据差别等或性能瓶颈。
  1. 根本概念:
  
  2. 主要特性:
  
  3. 使用场景:
  
  2.2  DruidDataSource(数据库连接池)

   DruidDataSource是阿里巴巴开源的一个高性能、可扩展的数据库连接池,他是Druid项目标一部门。Druid提供了一个丰富的功能,特殊适适用于生产环境中的Java应用步伐。
  1. 根本特性:
  
  2. 配置:
      Druid的配置非常灵活,可以通过XML、properties文件或Java代码进行配置,常见配置包罗:
  
  3. 监控与管理:
  
  4. 安全性
      Druid提供了一些安全特性,比如SQL防注入、优劣名单等。
  2.3  SqlSessionFactory (管理数据库连接和会话)

   SqlSessionFactory是MyBatis框架中用于创建SqlSessiobn的工厂接口。它是MyBatis的核心组件之一,负责管理数据库连接和会话的配置。
  1. 根本概念
  
  2. 创建SqlSessionFactory
      SqlSessionFactory的创建通常通过读取MyBatis的配置文件来实现。可以通过SqlSessionFactoryBuilder来构建它。
  3. mybatis-config.xml的配置:
  
  4. 线程安全:
       SqlSessionFactory是线程安全的,可以在应用中共享,每个线程应该自己创建SqlSession实例,而不是共享SqlSession对象。
  5. 常见题目:
  
  2.4 Mapper (定义数据库操作)

    Mapper是MyBatis的紧张构成部门,它用于定义数据库操作的方法并将这些方法与SQL语句映射。
  3. 代码实现

3.1 添加依赖:

  1. <dependency>
  2.     <groupId>com.alibaba</groupId>
  3.     <artifactId>druid</artifactId>
  4.     <version>1.2.9</version>
  5. </dependency>
  6. <dependency>
  7.     <groupId>org.mybatis</groupId>
  8.     <artifactId>mybatis</artifactId>
  9.     <version>3.5.13</version>
  10. </dependency>
复制代码
3.2 配置文件配置主数据库信息

  1. #oracle
  2. spring.datasource.dynamic.primary=anita
  3. spring.datasource.dynamic.datasource.anita.url=jdbc:oracle:thin:@oracle_url
  4. spring.datasource.dynamic.datasource.anita.driver-class-name=oracle.jdbc.OracleDriver
  5. spring.datasource.dynamic.datasource.anita.username=anita
  6. spring.datasource.dynamic.datasource.anita.password=anitazxq
复制代码
3.3 定义实体类

3.3.1 base_datasource实体类:DataSourceModel 

  1. package com.example.dataSource.dto;
  2. import com.baomidou.mybatisplus.annotation.TableName;
  3. import lombok.AllArgsConstructor;
  4. import lombok.Data;
  5. import lombok.NoArgsConstructor;
  6. @Data
  7. @NoArgsConstructor
  8. @AllArgsConstructor
  9. @TableName("base_datasource")
  10. public class DataSourceModel {
  11.     private String id;
  12.     private String dbname;
  13.     private String dbuser;
  14.     private String dbpassword;
  15.     private String dburl;
  16.     private String dbdriver;
  17. }
复制代码
 3.3.2 base_person的实体类:BasePersonModel 

  1. package com.example.dataSource.dto;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. @Data
  6. @NoArgsConstructor
  7. @AllArgsConstructor
  8. public class BasePersonModel {
  9.     private String id;
  10.     private String name;
  11. }
复制代码
3.4 定义Mapper 

3.4.1 DataSourceModel对应的Mapper:DataSourceMapper 

  1. package com.example.dataSource.mapper;
  2. import com.baomidou.dynamic.datasource.annotation.DS;
  3. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4. import com.example.dataSource.dto.DataSourceModel;
  5. import org.apache.ibatis.annotations.Mapper;
  6. @Mapper
  7. @DS("anita")  //指定数据源
  8. public interface DataSourceMapper extends BaseMapper<DataSourceModel> {
  9. }
复制代码
3.4.2  BasePersonModel 对应的Mapper:BasePersonMapper 

  1. package com.example.dataSource.mapper;
  2. import com.example.dataSource.dto.BasePersonModel;
  3. import org.apache.ibatis.annotations.Select;
  4. import java.util.List;
  5. public interface BasePersonMapper {
  6.     @Select("SELECT * FROM base_person")
  7.     List<BasePersonModel> getAllData();
  8. }
复制代码
3.5 定义Service层

   根据dbName查询数据库连接信息
  1. package com.example.dataSource.service;
  2. import com.alibaba.druid.pool.DruidDataSource;
  3. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4. import com.example.dataSource.dto.BasePersonModel;
  5. import com.example.dataSource.dto.DataSourceModel;
  6. import com.example.dataSource.mapper.BasePersonMapper;
  7. import com.example.dataSource.mapper.DataSourceMapper;
  8. import com.example.dataSource.utils.DataSourceCacheUtil;
  9. import com.example.dataSource.utils.MyBatisUtil;
  10. import org.apache.ibatis.session.SqlSession;
  11. import org.apache.ibatis.session.SqlSessionFactory;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.stereotype.Service;
  14. import java.util.List;
  15. @Service
  16. public class DataOperateService {
  17.     @Autowired
  18.     private DataSourceMapper dataSourceMapper;
  19.     //根据数据源名称查询数据库信息
  20.     public DataSourceModel getDataSourceByDbName(String dbName)
  21.     {
  22.         QueryWrapper<DataSourceModel> queryWrapper=new QueryWrapper<>();
  23.         queryWrapper.eq("dbname",dbName);
  24.         DataSourceModel dataSource=dataSourceMapper.selectOne(queryWrapper);
  25.         return dataSource;
  26.     }
  27. }
复制代码
 3.6 数据库连接池

  1. package com.example.dataSource.utils;
  2. import com.alibaba.druid.pool.DruidDataSource;
  3. import com.example.dataSource.dto.DataSourceModel;
  4. import org.springframework.stereotype.Component;
  5. @Component
  6. public class DataSourceConnectionUtil {
  7.     //创建数据库连接池
  8.     public static DruidDataSource createDataSource(DataSourceModel dataSourceModel)
  9.     {
  10.         DruidDataSource dataSource=new DruidDataSource();
  11.         dataSource.setDriverClassName(dataSourceModel.getDbdriver());
  12.         dataSource.setUrl(dataSourceModel.getDburl());
  13.         dataSource.setUsername(dataSourceModel.getDbuser());
  14.         dataSource.setPassword(dataSourceModel.getDbpassword());
  15.         dataSource.setValidationQuery("SELECT 1 FROM DUAL");//ORACLE验证查询
  16.         dataSource.setTestWhileIdle(true);
  17.         dataSource.setTestWhileIdle(false);
  18.         dataSource.setTestOnReturn(false);
  19.         //避免连接数一直增加
  20.         dataSource.setKeepAlive(false);
  21.         //设置keepAlive的时间间隔,单位毫秒
  22.         dataSource.setKeepAliveBetweenTimeMillis(60000);
  23.         dataSource.setTimeBetweenEvictionRunsMillis(50000);
  24.         dataSource.setMinEvictableIdleTimeMillis(300000);
  25.         dataSource.setMaxEvictableIdleTimeMillis(480000);
  26.         dataSource.setBreakAfterAcquireFailure(true);
  27.         dataSource.setConnectionErrorRetryAttempts(1);
  28.         dataSource.setMinIdle(5);
  29.         dataSource.setMaxActive(200);
  30.         dataSource.setMaxWait(30000);
  31.         return dataSource;
  32.     }
  33. }
复制代码
3.7  缓存池

  1. package com.example.dataSource.utils;
  2. import com.alibaba.druid.pool.DruidDataSource;
  3. import com.example.dataSource.dto.DataSourceModel;
  4. import com.example.dataSource.service.DataOperateService;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Component;
  7. import java.util.concurrent.ConcurrentHashMap;
  8. @Component
  9. public class DataSourceCacheUtil {
  10.     @Autowired
  11.     private DataOperateService dataOperateService;
  12.     @Autowired
  13.     private DataSourceConnectionUtil dataSourceConnectionUtil;
  14.     private static final ConcurrentHashMap<String, DruidDataSource> dataSourceCache=new ConcurrentHashMap<>();
  15.     //获取数据库连接
  16.     public DruidDataSource getDataSource(String dbName)
  17.     {
  18.         //从缓存池中获取数据库信息
  19.         DruidDataSource dataSource=dataSourceCache.get(dbName);
  20.         if(dataSource==null)
  21.         {
  22.             DataSourceModel ds=dataOperateService.getDataSourceByDbName(dbName);
  23.             //创建数据库连接池
  24.             dataSource=dataSourceConnectionUtil.createDataSource(ds);
  25.         }
  26.         dataSourceCache.put(dbName,dataSource);
  27.         return dataSource;
  28.     }
  29.     //在应用结束时关闭数据库连接池
  30.     public void close()
  31.     {
  32.         for(DruidDataSource dataSource : dataSourceCache.values())
  33.         {
  34.             dataSource.close();
  35.         }
  36.     }
  37. }
复制代码
 3.8 创建SqlSessionFactory

   初始化 MyBatis 所需的配置,并预备好一个可以用于数据库操作的 SqlSessionFactory 实例。通过这个工厂,应用步伐可以方便地获取 SqlSession,从而进行数据库操作。
  1. package com.example.dataSource.utils;
  2. import com.alibaba.druid.pool.DruidDataSource;
  3. import com.example.dataSource.mapper.BasePersonMapper;
  4. import org.apache.ibatis.mapping.Environment;
  5. import org.apache.ibatis.session.Configuration;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
  9. import javax.sql.DataSource;
  10. public class MyBatisUtil {
  11.     public static SqlSessionFactory getSqlSessionFactory(DruidDataSource dataSource)
  12.     {
  13.         // 创建 MyBatis 配置
  14.         Configuration configuration = new Configuration();
  15.         configuration.setEnvironment(new Environment("development", new JdbcTransactionFactory(), dataSource));
  16.         // 注册 Mapper
  17.         configuration.addMapper(BasePersonMapper.class);
  18.         // 返回 SqlSessionFactory
  19.         return new SqlSessionFactoryBuilder().build(configuration);
  20.     }
  21. }
复制代码
 3.9 从缓存池中获取目标数据库,查询数据。

   在2.5的DataOperateService 类中添加方法,实现以下功能:从缓存池中找到目标数据源,切换数据源,查询该数据源中的base_person表。
  1.     @Autowired
  2.     private DataSourceCacheUtil dataSourceCacheUtil;
  3.     public List<BasePersonModel> getData(String dbName)
  4.     {
  5.         DruidDataSource dataSource=dataSourceCacheUtil.getDataSource(dbName);
  6.         SqlSessionFactory sqlSessionFactory= MyBatisUtil.getSqlSessionFactory(dataSource);
  7.         // 获取 SqlSession
  8.         try(SqlSession sqlSession = sqlSessionFactory.openSession()){
  9.             // 获取 Mapper
  10.             BasePersonMapper basePersonMapper=sqlSession.getMapper(BasePersonMapper.class);
  11.             //查询
  12.             List<BasePersonModel> data=basePersonMapper.getAllData();
  13.             //sqlSession.commit();//如果执行的是insert、update操作,需要提交事务
  14.             return data;
  15.         }
  16.         catch (Exception e) {
  17.             // 记录异常或抛出自定义异常
  18.             e.printStackTrace();
  19.             // 这里可以根据需要返回空列表或重新抛出异常
  20.             return Collections.emptyList();
  21.         }
  22.     }
复制代码
2.10 通过接口将上述功能进行串联
  1. package com.example.dataSource.controller;
  2. import com.example.dataSource.dto.BasePersonModel;
  3. import com.example.dataSource.service.DataOperateService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import java.util.List;
  9. @RestController
  10. @RequestMapping("/api/differentDSUse")
  11. public class DataOperation {
  12.     @Autowired
  13.     DataOperateService dataOperateService;
  14.     @GetMapping("/search")
  15.     public List<BasePersonModel> get()
  16.     {
  17.         return dataOperateService.getData("test");
  18.     }
  19. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4