7.创建数据库连接池

1.直接上代码,不废话,创建一个一样名字的类,复制粘贴就OK

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 型

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

        this.jdbcDriver = jdbcDriver;
        this.dbUrl = dbUrl;
        this.dbUsername = dbUsername;
        this.dbPassword = dbPassword;
    }

    public int getInitialConnections() {
        return this.initialConnections;
    }

    public void setInitialConnections(int initialConnections) {
        this.initialConnections = initialConnections;
    }

    public int getIncrementalConnections() {
        return this.incrementalConnections;
    }

    public void setIncrementalConnections(int incrementalConnections) {
        this.incrementalConnections = incrementalConnections;
    }

    public int getMaxConnections() {
        return this.maxConnections;
    }

    public void setMaxConnections(int maxConnections) {
        this.maxConnections = maxConnections;
    }

    public String getTestTable() {
        return this.testTable;
    }

    public void setTestTable(String testTable) {
        this.testTable = testTable;
    }

    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(" 数据库连接池创建成功! ");
    }

    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(" 数据库连接己创建 ......");
        }
    }

    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; // 返回创建的新的数据库连接
    }

    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; // 返回获得的可用的连接
    }

    private Connection getFreeConnection() throws SQLException {
        // 从连接池中获得一个可用的数据库连接
        Connection conn = findFreeConnection();
        if (conn == null) {
            // 假如目前连接池中没有可用的连接
            // 创建一些连接
            createConnections(incrementalConnections);
            // 重新从池中查找是否有可用连接
            conn = findFreeConnection();
            if (conn == null) {
                // 假如创建连接后仍获得不到可用的连接,则返回 null
                return null;
            }
        }
        return conn;
    }

    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; // 返回找到到的可用连接
    }

    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;
    }

    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;
    }

    private void closeConnection(Connection conn) {
        try {
            conn.close();
        } catch (SQLException e) {
            System.out.println(" 关闭数据库连接出错: " + e.getMessage());
        }
    }

    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;
        }
    }
    public static ConnectionPool connPool=null;
    //获取数据库连接的方法
    public static Connection getConnectionObject(){
         try {
             Connection connection = connPool.getConnection();
              return connection;
         } catch (SQLException ex1) {
             ex1.printStackTrace();
             return null;
         }
    }
    //释放数据库连接
    public  static void releseConnectionObject(Connection conn){
        connPool.returnConnection(conn);
    }
}
时间: 2024-10-29 10:45:56

7.创建数据库连接池的相关文章

通过实现ServletContextListener接口创建数据库连接池(C3P0方式)

使用Listener步骤 1. 定义Listener实现类 2. 在web.xml中配置(或使用Annotation) 使用C3P0方式创建数据库连接池需要添加的jar包 1.c3p0-0.9.5.jar 2.c3p0-oracle-thin-extras-0.9.5.jar 3.mchange-commons-java-0.2.9.jar 1 package cn.sdut.lah.listener; 2 3 import java.sql.Connection; 4 import javax

glassfish中新建数据源(创建数据库连接池)

1.浏览器输入:http://localhost:4848 登录glassfish域管理控制台,默认的用户名和密码是amin和adminadmin.(也可以通过NetBeans的服务选项卡--服务器--GlassFishServer--右键,查看域管理控制中心) 2.新建数据库连接池: 3.新建jdbc资源: 输入JNDI名称,选择刚创建的连接池. 当然如果你使用NetBeans的话,有一个简单的方法,在你通过数据库生成实体类的时候,ide会提示你一步步的创建数据源. 选中包--右键新建,通过数

数据库连接池的理解和使用

一.什么是数据库连接池? 官方:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放. 个人理解:创建数据库连接是一个很耗时的操作,也容易对数据库造成安全隐患.所以,在程序初始化的时候,集中创建多个数据库连接,并把他们集中管理,供程序使用,可以保证较快的数据库读写速度,还更加安全可靠. 二.数据库连接池的运行机制 (1) 程序初始化时创建连接池 (2) 使用时向连接池申请可用连接 (3) 使

javaweb学习总结(三十九)——数据库连接池

一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出.拓机.如下图所示: 二.使用数据库连接池优化程序性能 2.1.数据库连接池的基本概念 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性

c++ 实现数据库连接池

c++ 实现数据库连接池 自己尝试用c++ 新标准实现了数据库连接池,代码简化了很多. 思路: 将数据库的连接当作一个对象添加进list队列中,在连接池创建的时候就建立好队列,并添加自定义大小的连接对象,连接对象用智能指针来管理(现代c++中不应该出现delete语句),避免类似内存泄漏等内存问题,智能指针上用lambda表达式注册了delete删除函数来释放连接资源,及时归还,(其中用了std::move来转移list中的对象所有权到函数里的临时智能指针对象,当离开作用域时,自动释放.) 关于

(转)数据库连接池的理解和使用

一.什么是数据库连接池? 官方:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申 请,使用,释放. 个人理解:创建数据库连接是一个很耗时的操作,也容易对数据库造成安全隐患.所以,在程序初始化的时候,集中创建多个数据库连接,并把他们 集中管理,供程序使用,可以保证较快的数据库读写速度,还更加安全可靠. 二.数据库连接池的运行机制 (1) 程序初始化时创建连接池 (2) 使用时向连接池申请可用连接 (3)

开源数据库连接池之C3P0

本篇介绍几种开源数据库连接池,同时重点讲述如何使用C3P0数据库连接池. 之前的博客已经重点讲述了使用数据库连接池的好处,即是将多次创建连接转变为一次创建而使用长连接模式.这样能减少数据库创建连接的消耗.正是由于数据库连接池的思想非常重要,所以市面上也有很多开源的数据库连接池供我们使用.主要有以下三个: DBCP数据库连接池 C3P0 数据库连接池 Tomcat内置的数据库连接池(DBCP) 本篇主要讲述C3P0数据库连接池的使用,关于另外两个数据库连接池的用法请看<开源数据库连接池之DBCP>

初识数据库连接池开源框架Druid

Druid是阿里巴巴的一个数据库连接池开源框架,准确来说它不仅仅包括数据库连接池这么简单,它还提供强大的监控和扩展功能.本文仅仅是在不采用Spring框架对Druid的窥探,采用目前最新版本druid1.0.26 github地址:https://github.com/alibaba/druid. 在开始之前还是再说说为什么不配套使用Spring来使用Druid连接池,原因其实很简单,在Spring框架的配置文件中仅仅一个配置datasource就可以使用Druid了.那到底配置这个dataso

数据库连接池(为数据统一连接建立一个缓冲池,现在企业开发使用)

数据库连接池:(里面放了许多连接数据的链接,负责分配,管理,释放数据库连接,可重复使用连接,而不新建  )为数据统一连接建立一个缓冲池,放好了一定数据库连接,使用时在缓冲池里面拿,用完之后再还给缓冲池,再使用时,不需要新建: --------------------------------------------------------------------------------------- 基本方法: /* * DBCP数据源:需要使用架包dbcp.jar *1.加入jar包,依赖于Co