数据库连接池 原理 示例

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.Vector;

public class ConnectionPool {

private String jdbcDriver = ""; // 数据库驱动

private String dbUrl = ""; // 数据 URL

private String dbUsername = ""; // 数据库用户名

private String dbPassword = ""; // 数据库用户密码

private String testTable = ""; // 测试连接是否可用的测试表名,默认没有测试表

private int initialConnections = 10; // 连接池的初始大小

private int incrementalConnections = 5;// 连接池自动增加的大小

private int maxConnections = 50; // 连接池最大的大小

private Vector connections = null; // 存放连接池中数据库连接的向量 , 初始时为 null

// 它中存放的对象为 PooledConnection 型

/**

* 构造函数

*

* @param jdbcDriver String JDBC 驱动类串

* @param dbUrl String 数据库 URL

* @param dbUsername String 连接数据库用户名

* @param dbPassword String 连接数据库用户的密码

*

*/

public ConnectionPool(String jdbcDriver,String dbUrl,String dbUsername,String dbPassword) {

this.jdbcDriver = jdbcDriver;

this.dbUrl = dbUrl;

this.dbUsername = dbUsername;

this.dbPassword = dbPassword;

}

/**

* 返回连接池的初始大小

*

* @return 初始连接池中可获得的连接数量

*/

public int getInitialConnections() {

return this.initialConnections;

}

/**

* 设置连接池的初始大小

*

* @param 用于设置初始连接池中连接的数量

*/

public void setInitialConnections(int initialConnections) {

this.initialConnections = initialConnections;

}

/**

* 返回连接池自动增加的大小 、

*

* @return 连接池自动增加的大小

*/

public int getIncrementalConnections() {

return this.incrementalConnections;

}

/**

* 设置连接池自动增加的大小

* @param 连接池自动增加的大小

*/

public void setIncrementalConnections(int incrementalConnections) {

this.incrementalConnections = incrementalConnections;

}

/**

* 返回连接池中最大的可用连接数量

* @return 连接池中最大的可用连接数量

*/

public int getMaxConnections() {

return this.maxConnections;

}

/**

* 设置连接池中最大可用的连接数量

*

* @param 设置连接池中最大可用的连接数量值

*/

public void setMaxConnections(int maxConnections) {

this.maxConnections = maxConnections;

}

/**

* 获取测试数据库表的名字

*

* @return 测试数据库表的名字

*/

public String getTestTable() {

return this.testTable;

}

/**

* 设置测试表的名字

* @param testTable String 测试表的名字

*/

public void setTestTable(String testTable) {

this.testTable = testTable;

}

/**

*

* 创建一个数据库连接池,连接池中的可用连接的数量采用类成员

* initialConnections 中设置的值

*/

public synchronized void createPool() throws Exception {

// 确保连接池没有创建

// 如果连接池己经创建了,保存连接的向量 connections 不会为空

if (connections != null) {

return; // 如果己经创建,则返回

}

// 实例化 JDBC Driver 中指定的驱动类实例

Driver driver = (Driver) (Class.forName(this.jdbcDriver).newInstance());

DriverManager.registerDriver(driver); // 注册 JDBC 驱动程序

// 创建保存连接的向量 , 初始时有 0 个元素

connections = new Vector();

// 根据 initialConnections 中设置的值,创建连接。

createConnections(this.initialConnections);

System.out.println(" 数据库连接池创建成功! ");

}

/**

* 创建由 numConnections 指定数目的数据库连接 , 并把这些连接

* 放入 connections 向量中

*

* @param numConnections 要创建的数据库连接的数目

*/

@SuppressWarnings("unchecked")
private void createConnections(int numConnections) throws SQLException {

// 循环创建指定数目的数据库连接

for (int x = 0; x < numConnections; x++) {

// 是否连接池中的数据库连接的数量己经达到最大?最大值由类成员 maxConnections

// 指出,如果 maxConnections 为 0 或负数,表示连接数量没有限制。

// 如果连接数己经达到最大,即退出。

if (this.maxConnections > 0 && this.connections.size() >= this.maxConnections) {

break;

}

//add a new PooledConnection object to connections vector

// 增加一个连接到连接池中(向量 connections 中)

try{

connections.addElement(new PooledConnection(newConnection()));

}catch(SQLException e){

System.out.println(" 创建数据库连接失败! "+e.getMessage());

throw new SQLException();

}

System.out.println(" 数据库连接己创建 ......");

}

}

/**

* 创建一个新的数据库连接并返回它

*

* @return 返回一个新创建的数据库连接

*/

private Connection newConnection() throws SQLException {

// 创建一个数据库连接

Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);

// 如果这是第一次创建数据库连接,即检查数据库,获得此数据库允许支持的

// 最大客户连接数目

//connections.size()==0 表示目前没有连接己被创建

if (connections.size() == 0) {

DatabaseMetaData metaData = conn.getMetaData();

int driverMaxConnections = metaData.getMaxConnections();

// 数据库返回的 driverMaxConnections 若为 0 ,表示此数据库没有最大

// 连接限制,或数据库的最大连接限制不知道

//driverMaxConnections 为返回的一个整数,表示此数据库允许客户连接的数目

// 如果连接池中设置的最大连接数量大于数据库允许的连接数目 , 则置连接池的最大

// 连接数目为数据库允许的最大数目

if (driverMaxConnections > 0 && this.maxConnections > driverMaxConnections) {

this.maxConnections = driverMaxConnections;

}

}

return conn; // 返回创建的新的数据库连接

}

/**

* 通过调用 getFreeConnection() 函数返回一个可用的数据库连接 ,

* 如果当前没有可用的数据库连接,并且更多的数据库连接不能创

* 建(如连接池大小的限制),此函数等待一会再尝试获取。

*

* @return 返回一个可用的数据库连接对象

*/

public synchronized Connection getConnection() throws SQLException {

// 确保连接池己被创建

if (connections == null) {

return null; // 连接池还没创建,则返回 null

}

Connection conn = getFreeConnection(); // 获得一个可用的数据库连接

// 如果目前没有可以使用的连接,即所有的连接都在使用中

while (conn == null){

// 等一会再试

wait(250);

conn = getFreeConnection(); // 重新再试,直到获得可用的连接,如果

//getFreeConnection() 返回的为 null

// 则表明创建一批连接后也不可获得可用连接

}

return conn;// 返回获得的可用的连接

}

/**

* 本函数从连接池向量 connections 中返回一个可用的的数据库连接,如果

* 当前没有可用的数据库连接,本函数则根据 incrementalConnections 设置

* 的值创建几个数据库连接,并放入连接池中。

* 如果创建后,所有的连接仍都在使用中,则返回 null

* @return 返回一个可用的数据库连接

*/

private Connection getFreeConnection() throws SQLException {

// 从连接池中获得一个可用的数据库连接

Connection conn = findFreeConnection();

if (conn == null) {

// 如果目前连接池中没有可用的连接

// 创建一些连接

createConnections(incrementalConnections);

// 重新从池中查找是否有可用连接

conn = findFreeConnection();

if (conn == null) {

// 如果创建连接后仍获得不到可用的连接,则返回 null

return null;

}

}

return conn;

}

/**

* 查找连接池中所有的连接,查找一个可用的数据库连接,

* 如果没有可用的连接,返回 null

*

* @return 返回一个可用的数据库连接

*/

private Connection findFreeConnection() throws SQLException {

Connection conn = null;

PooledConnection pConn = null;

// 获得连接池向量中所有的对象

Enumeration enumerate = connections.elements();

// 遍历所有的对象,看是否有可用的连接

while (enumerate.hasMoreElements()) {

pConn = (PooledConnection) enumerate.nextElement();

if (!pConn.isBusy()) {

// 如果此对象不忙,则获得它的数据库连接并把它设为忙

conn = pConn.getConnection();

pConn.setBusy(true);

// 测试此连接是否可用

if (!testConnection(conn)) {

// 如果此连接不可再用了,则创建一个新的连接,

// 并替换此不可用的连接对象,如果创建失败,返回 null

try{

conn = newConnection();

}catch(SQLException e){

System.out.println(" 创建数据库连接失败! "+e.getMessage());

return null;

}

pConn.setConnection(conn);

}

break; // 己经找到一个可用的连接,退出

}

}

return conn;// 返回找到到的可用连接

}

/**

* 测试一个连接是否可用,如果不可用,关掉它并返回 false

* 否则可用返回 true

*

* @param conn 需要测试的数据库连接

* @return 返回 true 表示此连接可用, false 表示不可用

*/

private boolean testConnection(Connection conn) {

try {

// 判断测试表是否存在

if (testTable.equals("")) {

// 如果测试表为空,试着使用此连接的 setAutoCommit() 方法

// 来判断连接否可用(此方法只在部分数据库可用,如果不可用 ,

// 抛出异常)。注意:使用测试表的方法更可靠

conn.setAutoCommit(true);

} else {// 有测试表的时候使用测试表测试

//check if this connection is valid

Statement stmt = conn.createStatement();

stmt.execute("select count(*) from " + testTable);

}

} catch (SQLException e) {

// 上面抛出异常,此连接己不可用,关闭它,并返回 false;

closeConnection(conn);

return false;

}

// 连接可用,返回 true

return true;

}

/**

* 此函数返回一个数据库连接到连接池中,并把此连接置为空闲。

* 所有使用连接池获得的数据库连接均应在不使用此连接时返回它。

*

* @param 需返回到连接池中的连接对象

*/

public void returnConnection(Connection conn) {

// 确保连接池存在,如果连接没有创建(不存在),直接返回

if (connections == null) {

System.out.println(" 连接池不存在,无法返回此连接到连接池中 !");

return;

}

PooledConnection pConn = null;

Enumeration enumerate = connections.elements();

// 遍历连接池中的所有连接,找到这个要返回的连接对象

while (enumerate.hasMoreElements()) {

pConn = (PooledConnection) enumerate.nextElement();

// 先找到连接池中的要返回的连接对象

if (conn == pConn.getConnection()) {

// 找到了 , 设置此连接为空闲状态

pConn.setBusy(false);

break;

}

}

}

/**

* 刷新连接池中所有的连接对象

*

*/

public synchronized void refreshConnections() throws SQLException {

// 确保连接池己创新存在

if (connections == null) {

System.out.println(" 连接池不存在,无法刷新 !");

return;

}

PooledConnection pConn = null;

Enumeration enumerate = connections.elements();

while (enumerate.hasMoreElements()) {

// 获得一个连接对象

pConn = (PooledConnection) enumerate.nextElement();

// 如果对象忙则等 5 秒 ,5 秒后直接刷新

if (pConn.isBusy()) {

wait(5000); // 等 5 秒

}

// 关闭此连接,用一个新的连接代替它。

closeConnection(pConn.getConnection());

pConn.setConnection(newConnection());

pConn.setBusy(false);

}

}

/**

* 关闭连接池中所有的连接,并清空连接池。

*/

public synchronized void closeConnectionPool() throws SQLException {

// 确保连接池存在,如果不存在,返回

if (connections == null) {

System.out.println(" 连接池不存在,无法关闭 !");

return;

}

PooledConnection pConn = null;

Enumeration enumerate = connections.elements();

while (enumerate.hasMoreElements()) {

pConn = (PooledConnection) enumerate.nextElement();

// 如果忙,等 5 秒

if (pConn.isBusy()) {

wait(5000); // 等 5 秒

}

//5 秒后直接关闭它

closeConnection(pConn.getConnection());

// 从连接池向量中删除它

connections.removeElement(pConn);

}

// 置连接池为空

connections = null;

}

/**

* 关闭一个数据库连接

*

* @param 需要关闭的数据库连接

*/

private void closeConnection(Connection conn) {

try {

conn.close();

}catch (SQLException e) {

System.out.println(" 关闭数据库连接出错: "+e.getMessage());

}

}

/**

* 使程序等待给定的毫秒数

*

* @param 给定的毫秒数

*/

private void wait(int mSeconds) {

try {

Thread.sleep(mSeconds);

} catch (InterruptedException e) {

}

}

/**

*

* 内部使用的用于保存连接池中连接对象的类

* 此类中有两个成员,一个是数据库的连接,另一个是指示此连接是否

* 正在使用的标志。

*/

class PooledConnection {

Connection connection = null;// 数据库连接

boolean busy = false; // 此连接是否正在使用的标志,默认没有正在使用

// 构造函数,根据一个 Connection 构告一个 PooledConnection 对象

public PooledConnection(Connection connection) {

this.connection = connection;

}

// 返回此对象中的连接

public Connection getConnection() {

return connection;

}

// 设置此对象的,连接

public void setConnection(Connection connection) {

this.connection = connection;

}

// 获得对象连接是否忙
public boolean isBusy() {
return busy;
}
// 设置对象的连接正在忙

public void setBusy(boolean busy) {

this.busy = busy;

}
}

}

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

这个例子是根据POSTGRESQL数据库写的,
请用的时候根据实际的数据库调整。

调用方法如下:

① ConnectionPool connPool
= new ConnectionPool("org.postgresql.Driver"
,"jdbc:postgresql://dbURI:5432/DBName"
,"postgre"
,"postgre");

② connPool .createPool();
Connection conn = connPool .getConnection();
Spring Cloud 整合(一) CRUD Springcloud 整合之 CRUDSpringcloud介绍功能概述为什么要选用Springcloud Springcloud介绍 功能概述 实现微服务 Spring Cloud为开发人员提供了工具,以快速构建分布式系统中的某些常见模式(例如,配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,群集状态)。分布式系统的协调导致样板式样,并且使用Spring Cloud开发人员可以快速站起来实现这些样板的服务和应用程序。 为什么要选用Springcloud 阅读详情

相关推荐

1.全基因组重测序数据分析介绍

二代测序原理及fastq数据解读、全基因组重测序数据分析内容

weixin_53682198的博客 1842

Java-MySQL连接池Druid

需要注意的是,设置的最大等待时间并不是连接的最长生命周期,连接池中的连接可能会被定时清理,这取决于连接池的配置。Druid连接池内置了一些常用的拦截器,可以直接使用,也可以根据自己的需求进行扩展。Alibaba的Druid是一款开源的高性能JDBC连接池和监控工具,它不仅仅具有连接池的基本功能,还提供了强大的监控、统计和SQL调优功能,使得开发人员可以更好地管理和优化数据库连接和SQL查询。需要注意的是,拦截器的使用可能会影响到系统的性能,尤其是在高并发的情况下,因此需要根据应用的实际情况进行选择和配置。

weixin_49031148的博客 1665

Spring Boot与HikariCP:性能卓越的数据库连接池

本文将详细介绍Spring Boot中如何使用HikariCP作为数据库连接池,包括其工作原理、优势分析、配置步骤以及代码示例。通过本文,读者将能够轻松集成HikariCP到Spring Boot项目中,从而提高数据库连接的性能和效率。

a342874650的专栏 2436

学习DatabaseConnectionPool--数据库连接池(随记三)

         连接池建立起来后的应用就相对简单多了,不过事情往往不是都很顺利的,一套完整的应用是需要所有细节的链子完整的连接起来,这中间需要进行一些琐碎的工作。       我使用的数据库是 ms sql server,配置需要花费一些手脚。        1.下载sql server的驱动,有3个文件:msbase.jar、mssqlserver.jar、msutil.jar。具体只

落寞风聚沙—— 1267

commons-dbcp数据库连接池基本使用

简介: commons-dbcp工具包是用来提供数据库连接池服务. 话不多说,奉上使用方法: ①引入maven依赖 <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <v...

淋雨一直走啊 6455

java mysql数据库连接池DruidPool配置及表操作实现方法

4.my sql版本 5 驱动版本:mysql-connector-java-5.1.46-bin.jar。5.durid连接池版本 druid-1.0.29.jar。2.操作系统 windows10。3.tomcat 版本 9.0。1.jdk版本 1.8。

qq_38978908的博客 1897

apache commons-dbcp Apache Commons DBCP 软件实现数据库连接池 commons-dbcp2

对于一个公开托管在互联网上的应用程序,在同时在线用户数量可能非常大的情况下,为每个用户打开一个连接可能是不可行的。在任何给定时间实际执行请求的用户数量通常只是活跃用户总数的非常小的百分比,在请求处理期间是唯一需要数据库连接的时间。升级到2.x的用户应该注意到Java包名称已更改,以及Maven坐标已更改,因为DBCP 2.x与DBCP 1.x不是二进制兼容的。应用程序运行在Java 8及以上版本的情况下,应使用DBCP 2.5.0及以上版本的二进制文件。这里用的是 dbcp 的驱动实现池化的?

1658

讲的非常详细的 数据库连接池 原理 示例

import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.Driver;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;import java.util.Enu

波波的专栏 752

数据库连接池-Durid连接池

然后通过 `dataSource.init()` 方法初始化数据源,调用 `dataSource.getConnection()` 方法从连接池中获取一个数据库连接,执行数据库操作后,通过 `connection.close()` 将连接放回连接池数据库连接池是一个存放数据库连接的缓冲池,它能够管理和重用数据库连接,从而提高数据库访问的性能和效率。数据库连接是一种资源,它的创建和销毁是比较耗时的操作,因此使用连接池可以避免频繁地创建和销毁连接,从而减少了系统资源的消耗,提高了系统的响应速度和稳定性。

m0_65037354的博客 748

Delphi语言的数据库连接池

数据库连接池是为了提高数据库访问性能而设计的一种技术。通常情况下,建立和关闭数据库连接都是相对耗时的操作,尤其是在高并发的情况下,频繁地建立连接可能会导致性能瓶颈。连接池通过维护一个可重用的连接集合,允许多个用户或线程共享连接,从而显著减少建立连接的时间。数据库连接池作为一种重要的性能优化手段,在Delphi应用程序的开发中起着至关重要的作用。通过合理的实现和配置,连接池能显著提高数据库访问的性能,降低资源消耗并提升用户体验。希望本文提供的理论分析与实用示例能够帮助开发者更好地理解和运用数据库连接池技术。

2501_91275982的博客 551

数据库连接池技术 之 DBCP

DBCP的工作原理是,程序首先会初始化相应的数据库连接池,以供程序访问,当某个操作需要访问数据库时,程序会首先在连接池中取得空闲连接,如没有空闲连接在创建,用完之后归还连接池,这样达到了连接的重利用,不用频繁的创建连接和销毁,从而优化程序。DBCP常见属性有:driver:数据库驱动,如 com.mysql.jdbc.Driverurl:数据库连接,如 jdbc:mysql://localhost:3306/testDBusername:数据库用户名,如 root。

2401_85158559的博客 1313

数据库连接池:提升数据库访问效率的关键技术

减少重复劳动:餐厅(数据库)不需要每次为顾客(程序)安排新座位(连接),直接从池中取用。节省时间:顾客(程序)可以立即入座(获取连接),提高了用餐(查询)效率。资源共享:多个顾客(程序)共享座位(连接),避免了每次都重新准备新座位。减少等待:当池中有空座位时,顾客可以快速入座,池满时顾客只能等待,直到有座位空出来。

qq_42194776的博客 2085

MyBatis的数据库连接池故障处理实例

1.背景介绍 MyBatis是一款优秀的Java持久化框架,它可以简化数据库操作,提高开发效率。在实际项目中,MyBatis通常需要与数据库连接池(如Druid、HikariCP等)配合使用,以提高数据库连接的复用率和性能。然而,在使用过程中,我们可能会遇到一些数据库连接池的故障问题,如连接池泄漏、连接超时、连接不可用等。本文将从MyBatis的数据库连接池故障处理角度,为大家提供一些实际操作和...

AI天才研究院 1021

Java自定义连接池

java自定义连接池,模拟一下Druid中的一小段功能

weixin_53375372的博客 1063

连接池相关知识点||about database connection pool

0、javax.sql.PooledConnection 1、connection pooling(连接缓冲)=>database connection pool(数据库连接池)=>database physical connection(物理连接)||long connection(长连接) 2、Connection(数据库连接)-->Statement(会话声明)-->Resultset(...

can_do_it的专栏 415

Java | 详解 Java连接MySQL、编写JdbcUtils工具类、使用数据库连接池、使用JavaTemplate

使用java连接mysql数据库进行增删改查、编写JdbcUtils工具类、使用数据库连接池C3P0以及Druid、使用JavaTemplate

1万+

Database Connection Pool 数据库连接池-01-概览

拓展阅读 第一节 从零开始手写 mybatis(一)MVP 版本。 第二节 从零开始手写 mybatis(二)mybatis interceptor 插件机制详解 第三节 从零开始手写 mybatis(三)jdbc pool 从零实现数据库连接池 第四节 从零开始手写 mybatis(四)- mybatis 事务管理机制详解 连接池的作用 资源重用 由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上, 另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进

555

学习DatabaseConnectionPool--数据库连接池(随记二)

 一、从java类来分析连接池的构架,可以了解以下几点: 1. 连接池实际上分2个部分:连接池类和连接池管理类。  2. 连接池类作用是:创建和毁灭连接池、创建连接和关闭连接、遍历查询并提供有效连接、处理无效连接。  3. 连接池管理类的作用是:初始化操作(提供创建一个连接池的操作方法、获取数据库的用户密码驱动信息提供给连接池类使用)、从连接池获取有效连接提供给用户、追踪连接操作和记录日志。 

落寞风聚沙—— 3975

实现高效的数据库连接池(附带完整代码C#和Java实现)

相关技术: 连接池 引用记数 多线程 C#.Net Java 目录 引言 数据库连接池(Connection Pool)的工作原理 连接池关键问题分析 并发问题 事务处理 连接池的分配与释放 连接池的配置与维护 关键议题 引用记数 如何实现事务处理  管理连接池 结合代码说明 构造方法 启动服务

哈库纳 1万+

UniApp日志本地存储方案[源码]

本文详细介绍了在UniApp开发的App端实现日志本地存储的完整方案。该方案支持不同级别日志的记录(如info、warn、error等),自动记录日志时间和级别,并按日期分割日志文件以避免单个文件过大。同时提供了设置日志文件最大保存天数、日志文件清理功能,并确保在App重启后日志不会丢失。文中给出了一个基于UniApp文件系统API的完整日志工具类实现,包括初始化日志目录、写入日志、清理过期日志等核心功能,并提供了具体的使用方法示例,方便开发者在项目中快速集成和使用。

上一篇: 学习计划
下一篇: jquery实现多文件上传
pp263020776
博客等级 码龄18年 0粉丝 3原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值