Java数据库连接池原理与简易实现

简介: Java数据库连接池原理与简易实现

1、什么是数据库连接池

我们现在在开发中一定都会用到数据库,为了提高我们的系统的访问速度,数据库优化是一个有效的途径。


我们现在开发中使用数据库一般都要经历以下的四个步骤:

(1)加载数据库的驱动类,

(2)建立数据库连接,

(3)进行数据操作,

(4)关闭数据库连接;


在这四步中建立数据库连接是一个比较耗时的操作,如果每次有新的操作数据库的需求都去重新建立数据库连接必然要耗费一部分时间,拖慢系统的访问速度;在这种情况下我们就需要数据库连接池,预先创建好一定数量的数据库连接,等我们现需要使用时直接从其中拿已经创建好了尚未使用的的数据库连接,这样就可以节省掉一部分时间,加快系统的访问速度,保存这些预先创建的一定数量的数据库连接的容器称之为数据库连接池。


2、现有的常用数据库连接池

(1)DBCP数据库连接池

(2)C3P0数据库连接池


3、数据库连接池原理

数据库连接池通过预先创建一定数量的空闲的数据库连接,在需要数据库连接时直接从其中获取,而不要去重新创建而节省一定的时间。


数据库连接池的连接有连个属性,一个是本数据库的真正的连接对象,一个是标志本连接是否是空闲的标志;当数据库连接池被初始化的时候,会去创建一定数量(一般在配置文件中配置)的数据库连接,并且这些连接都是处于空闲状态的,当需要数据库连接时,直接从数据库连接池中获取已经创建并且空闲的数据库连 接 并将其致为非空闲状态,如果数据库连接池中没有了空闲的连接,则去看数据库连接池连接数量是否以达到最大值(一般在配置文件中配置),如果没有达到最 大 值则再去创建一定数量的空闲连接;当连接使用完毕后,并不真正的关闭连接,而是将连接的状态重新致为空闲。从而达到连接重复使用的效果,节省时间。


4、简易数据库连接池的实现

(1)、创建数据库连接池的对象,对象包括真正的数据库连接池对象和是否可用的标志。

importjava.sql.Connection;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importjava.sql.Statement;
/*** 数据库连接池对象*/publicclassSimplePoolEntity {
//真正的数据库连接对象privateConnectionconnection;
//是否可用的标志,默认为true 可用privatebooleanisUsable=true;
publicConnectiongetConnection() {
returnconnection;
    }
publicvoidsetConnection(Connectionconnection) {
this.connection=connection;
    }
publicbooleanisUsable() {
returnisUsable;
    }
publicvoidsetUsable(booleanusable) {
isUsable=usable;
    }
/*** 数据库操作方法* @param sql  需要执行的sql语句* @return  ResultSet*/publicResultSetexecSql(Stringsql){
ResultSetrs=null;
try {
Statementstatement=connection.createStatement();
rs=statement.executeQuery(sql);
        } catch (SQLExceptione) {
e.printStackTrace();
        }
returnrs;
    }
}


(2)数据库连接池操作接口

/*** 数据库连接池操作接口*/publicinterfaceSimplePoolService {
/*** 连接池创建连接接口* @param connCount  需要创建的连接数量*/voidcreateConnection(intconnCount) throwsException;
/*** 获取数据库连接* @return* @throws Exception*/SimplePoolEntitygetConnection();
}

(3)数据库连接池操作实现

数据库连接池配置文件:

#数据库的驱动类simple.jdbc.driver=com.mysql.jdbc.Driver#数据库的连接urlsimple.jdbc.url=jdbc:mysql://localhost:3306/test#数据库的连接用户名simple.jdbc.username=root#数据库的连接密码simpel.jdbc.password=root#数据库连接池的初始化连接数量simple.init.count=10#数据库连接池的步进数量simple.step.count=4#连接池的最大数量simple.max.count=100


数据库连接池的实现

/**数据库操作实现本操作中将要实现数据库连接池的初始化工作,初始化参数采用配置文件的形式来进行配置 */publicclassSimplePoolServiceImplimplementsSimplePoolService {
privateStringjdbcDriver; // 数据库驱动privateStringjdbcUrl;  //数据库urlprivateStringusername; //用户名privateStringpassword; //密码privateIntegerinitCount; //初始化数量privateIntegerstepCount;  //步进数量privateIntegermaxCount; //最大数量privateSimplePoolEntitysimplePoolEntity;
privateSet<SimplePoolEntity>simplePoolEntitySet=newHashSet<>();
/*** 构造方法初始化 数据库连接池*/publicSimplePoolServiceImpl(){
init();
    }
/*** 数据库连接池初始化*/privatevoidinit(){
//1.读取配置文件InputStreamin=this.getClass().getClassLoader().getResourceAsStream("simpleboolconfig.properties");
Propertiesproperties=newProperties();
try {
properties.load(in);
//设置初始化参数jdbcDriver=properties.getProperty("simple.jdbc.driver");
jdbcUrl=properties.getProperty("simple.jdbc.url");
username=properties.getProperty("simple.jdbc.username");
password=properties.getProperty("simpel.jdbc.password");
initCount=Integer.parseInt(properties.getProperty("simple.init.count"));
stepCount=Integer.parseInt( properties.getProperty("simple.step.count"));
maxCount=Integer.parseInt( properties.getProperty("simple.max.count"));
//加载数据库驱动Driverdriver= (Driver) Class.forName(jdbcDriver).newInstance();
//获取数据库管理对象DriverManager.deregisterDriver(driver);
//初始化一定数量的连接createConnection(initCount);
        } catch (Exceptione) {
e.printStackTrace();
        }
    }
@OverridepublicvoidcreateConnection(intconnCount) throwsException {
//判断数据库连接池是否以达到最大连接数if(simplePoolEntitySet.size() +connCount>maxCount){
thrownewRuntimeException("连接池数量已到上限");
        }
for (inti=0;i<connCount;i++){
simplePoolEntity=newSimplePoolEntity();
simplePoolEntity.setConnection(DriverManager.getConnection(jdbcUrl,username,password));
simplePoolEntity.setUsable(true);
simplePoolEntitySet.add(simplePoolEntity);
        }
    }
@OverridepublicSimplePoolEntitygetConnection()  {
try {
SimplePoolEntitysimplePoolEntity=getRealConection();
//为空时创建新的连接while (simplePoolEntity==null){
createConnection(stepCount);
//创建连接比较耗时,建议在此处让线程延迟一定时间Thread.sleep(3000);
simplePoolEntity=getRealConection();
            }
        } catch (Exceptione) {
e.printStackTrace();
        }
returnsimplePoolEntity;
    }
privateSimplePoolEntitygetRealConection() throwsException{
//循环连接池,获取连接for(SimplePoolEntitysimplePoolEntity : simplePoolEntitySet){
//判断是否为空闲if(simplePoolEntity.isUsable()){
//判断连接是否有效if(!simplePoolEntity.getConnection().isValid(3000)){
//无效连接,重新创建连接替换该连接ConnectionrealConnect=DriverManager.getConnection(jdbcUrl,username,password);
simplePoolEntity.setConnection(realConnect);
                }
//设置状态为不可用simplePoolEntity.setUsable(false);
returnsimplePoolEntity;
            }
        }
returnnull;
    }
}



 (4) 对外提供单例模式的数据库连接池管理对象


publicclassSimplePoolManger { 
//私有化构造,禁止创建 privateSimplePoolManger(){}
//在静态内部类中实例化对象,达到懒汉单例模式privatestaticclassClassLoad{
publicstaticSimplePoolServicegetSimplePoolService(){
returnnewSimplePoolServiceImpl();
         }
    }
publicstaticSimplePoolServicegetInstace(){
returnClassLoad.getSimplePoolService();
    }
}


相关文章
|
1月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
24天前
|
存储 缓存 Java
【高薪程序员必看】万字长文拆解Java并发编程!(5):深入理解JMM:Java内存模型的三大特性与volatile底层原理
JMM,Java Memory Model,Java内存模型,定义了主内存,工作内存,确保Java在不同平台上的正确运行主内存Main Memory:所有线程共享的内存区域,所有的变量都存储在主存中工作内存Working Memory:每个线程拥有自己的工作内存,用于保存变量的副本.线程执行过程中先将主内存中的变量读到工作内存中,对变量进行操作之后再将变量写入主内存,jvm概念说明主内存所有线程共享的内存区域,存储原始变量(堆内存中的对象实例和静态变量)工作内存。
60 0
|
2月前
|
NoSQL Java API
在Java环境下如何进行Redis数据库的操作
总的来说,使用Jedis在Java环境下进行Redis数据库的操作,是一种简单而高效的方法。只需要几行代码,就可以实现复杂的数据操作。同时,Jedis的API设计得非常直观,即使是初学者,也可以快速上手。
215 94
|
1月前
|
存储 安全 Java
深入探究Java中ThreadLocal的工作原理和用途
总结起来,ThreadLocal是Java多线程编程中一个非常有用的工具,通过为每个线程分配独立的变量副本,实现线程隔离,避免资
51 9
|
16天前
|
人工智能 JavaScript Java
Java反射机制及原理
本文介绍了Java反射机制的基本概念、使用方法及其原理。反射在实际项目中比代理更常用,掌握它可以提升编程能力并理解框架设计原理。文章详细讲解了获取Class对象的四种方式:对象.getClass()、类.class、Class.forName()和类加载器.loadClass(),并分析了Class.forName()与ClassLoader的区别。此外,还探讨了通过Class对象进行实例化、获取方法和字段等操作的具体实现。最后从JVM类加载机制角度解析了Class对象的本质及其与类和实例的关系,帮助读者深入理解Java反射的工作原理。
|
24天前
|
存储 安全 Java
【高薪程序员必看】万字长文拆解Java并发编程!(4-1):悲观锁底层原理与性能优化实战
目录4. JVM字节码文件4.1. 字节码文件-组成4.1.1. 组成-基础信息4.1.1.1. 基础信息-魔数4.1.1.2. 基础信息-主副版本号4.1.2. 组成-常量池4.1.3. 组成-方法4.1.3.1. 方法-工作流程4.1.4. 组成-字段4.1.5. 组成-属性4.2. 字节码文件-查看工具4.2.1. javap4.2.2. jclasslib4.2.3. 阿里Arthas
34 0
|
2月前
|
Java 关系型数据库 MySQL
Java汽车租赁系统源码(含数据库脚本)
Java汽车租赁系统源码(含数据库脚本)
50 4
|
3月前
|
存储 缓存 人工智能
【原理】【Java并发】【synchronized】适合中学者体质的synchronized原理
本文深入解析了Java中`synchronized`关键字的底层原理,从代码块与方法修饰的区别到锁升级机制,内容详尽。通过`monitorenter`和`monitorexit`指令,阐述了`synchronized`实现原子性、有序性和可见性的原理。同时,详细分析了锁升级流程:无锁 → 偏向锁 → 轻量级锁 → 重量级锁,结合对象头`MarkWord`的变化,揭示JVM优化锁性能的策略。此外,还探讨了Monitor的内部结构及线程竞争锁的过程,并介绍了锁消除与锁粗化等优化手段。最后,结合实际案例,帮助读者全面理解`synchronized`在并发编程中的作用与细节。
177 8
【原理】【Java并发】【synchronized】适合中学者体质的synchronized原理
|
3月前
|
消息中间件 Java 应用服务中间件
JVM实战—1.Java代码的运行原理
本文介绍了Java代码的运行机制、JVM类加载机制、JVM内存区域及其作用、垃圾回收机制,并汇总了一些常见问题。
JVM实战—1.Java代码的运行原理
|
3月前
|
前端开发 JavaScript Java
[Java计算机毕设]基于ssm的OA办公管理系统的设计与实现,附源码+数据库+论文+开题,包安装调试
OA办公管理系统是一款基于Java和SSM框架开发的B/S架构应用,适用于Windows系统。项目包含管理员、项目管理人员和普通用户三种角色,分别负责系统管理、请假审批、图书借阅等日常办公事务。系统使用Vue、HTML、JavaScript、CSS和LayUI构建前端,后端采用SSM框架,数据库为MySQL,共24张表。提供完整演示视频和详细文档截图,支持远程安装调试,确保顺利运行。
170 17