数据库连接池(DBCP)连接SQL、MySQL数据库

为什么使用数据库连接池

JDBC中,一个Connection对象表示一个对数据库的连接。建立一个连接耗时又耗资源,如果所有客户共享一组已经打开的连接会节约很多时间。

什么时候使用连接池

1.所有用户通过一个通用的数据库帐号访问数据库。
           2.
数据库连接只用于单个请求的持续时间,用完即归还连接

数据库连接池

连接池是存储、管理数据库连接的容器,应用程序把获取数据库连接的功能委托给连接池。每个连接池都有一个上限,如果连接池达到上限,应用程序线程申请连接时被堵塞,等待其他线程释放连接。使用连接池首先要获得对连接池对象的引用,这里的对象是唯一的。无论有多少个进程访问连接池,连接池对象只有一个实例,在整个程序运行期间,连接池对象要常驻内存。

数据库连接池影响因素

数据库连接池影响因素
最小连接数连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费。
最大连接数连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。
最小连接数与最大连接数差距最小连接数与最大连接数相差太大,那么最先的连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接。不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,它将被放到连接池中等待重复使用或是空闲超时后被释放。

注意:如果一个进程需要使用多个连接对象,那么连接池的最大连接数应大于单个进程需要的最大连接数。

进程(程序)使用连接池的一般步骤

  1. 获得一个或多个管理连接池的对象的引用
  2. 从连接池中获得一个连接
  3. 对获得的连接进行操作使用
  4. 操作完成,归还连接

数据库连接池连接SQL

  • 数据库连接池的重要对象和成员
数据库连接池的重要对象和成员
int minConn连接池最少连接数
int maxConn连接池最多连接数
Stack<Connection> connStack = new Stack<>(); 使用Stack保存数据库连接, 也可以使用数组, Vector等保存
private ConnManager()

构造函数功能:

1.初始化

2.打开Log文件

3.注册驱动程序

4.根据最小连接数生成连接

public static synchronized ConnManager getInstance()  返回连接池对象唯一实例。如果是第一次调用此方法,则调用创建该实例
private Connection newConnection()创建新的连接
public synchronized Connection getConnection()从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接数限制, 则创建新连接
public synchronized void freeConnection(Connection con) 将不再使用的连接返回给连接池

ConnManager.java

package org.DBCP.sql;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.Stack;

/**
 * @author Cqh_i 2018年7月19日20:49:19
 * SQL数据库连接池
 */

public class ConnManager {
    int minConn = 2; // 连接池最少连接数
    int maxConn = 5;// 连接池最多连接数
    String user = "sa"; // 连接数据库使用的用户名
    String password = "abc123!"; // 连接数据库使用的用户名密码
    String url = "jdbc:sqlserver://localhost:1433;DatabaseName=DBNAME";// 所连接的数据库的URL(连接字符串)
    String logFile = "E:\\Program Files (x86)\\Sql_log_file\\dbpool.log";// 日志文件路径
    PrintWriter loger = null; // 记录日志Log的对象
    int connAmount = 0; // 当前现有的连接的个数
    Stack<Connection> connStack = new Stack<>(); // 使用Stack保存数据库连接, 也可以使用数组, Vector等保存

    /**
     * 构造函数 功能: 1.初始化 2.打开Log文件 3.注册驱动程序 4.根据最小连接数生成连接
     */
    private ConnManager() {
        try {
            loger = new PrintWriter(new FileWriter(logFile, true), true);
        } catch (IOException ioe) {
            loger = new PrintWriter(System.err);
        }
        // 注册驱动程序
        try {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            log("成功注册驱动程序");
        } catch (Exception e) {
            log("无法注册驱动程序");
        }
        // 根据最少连接数生成连接
        for (int i = 0; i < minConn; i++) {
            Connection con = newConnection();
            if (con != null)
                connStack.push(con);
        }
    }

    // 将文本信息msg写入日志文件
    private void log(String msg) {
        loger.println(new Date() + ":" + msg);
    }

    private static ConnManager instance; // 数据库连接池ConnManager的实例

    public static synchronized ConnManager getInstance() {
        // 返回唯一实例。如果是第一次调用此方法,则创建该实例
        if (instance == null) {
            instance = new ConnManager();
        }
        return instance;
    }

    // 创建新的连接
    private Connection newConnection() {
        Connection con = null;
        try {
            con = DriverManager.getConnection(url, user, password);
            connAmount++;
            log("连接池创建一个新的连接");
        } catch (SQLException e) {
            log("无法创建下列url的连接: " + url);
            return null;
        }
        return con;
    }

    public synchronized Connection getConnection() {
        /**
         * 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接数限制, 则创建新连接
         */
        Connection con = null;
        log("从连接池申请一个连接");
        log("现在可用的连接总数为: " + connStack.size());
        if (!connStack.empty()) {
            con = (Connection) connStack.pop();
        } else if (connAmount < maxConn) {
            con = newConnection();
        } else {
            try {
                log("等待连接");
                wait(100000);// 等待其他进程释放连接,单位是毫秒
                return getConnection();
            } catch (InterruptedException ie) {

            }
        }
        return con;
    }

    public synchronized void freeConnection(Connection con) {
        // 将不再使用的连接返回给连接池
        connStack.push(con);
        notifyAll();// 唤醒在此对象监视器上等待的所有线程
        log("归还一个连接到连接池");
    }
}

对以上数据池进行简单测试,建立Test_DBCP.jsp文件

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page language="java" import="org.DBCP.sql.ConnManager, java.sql.*"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Test_DBCP</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>

<body>
    <%
        //1.得到连接池的唯一实例
        ConnManager pool = ConnManager.getInstance();
        //2.从连接池中获得一个连接
        Connection conn = pool.getConnection();

        /*
        3.对获得的连接进行操作使用
        */

        //4.操作完成,归还连接。
        if (conn != null)
            pool.freeConnection(conn);
    %>
</body>
</html>

运行结果查看log日志文件

数据库连接池连接MySQL

       MySQL的官方JDBC驱动程序MySQL Connector / J官网下载地址:https://dev.mysql.com/downloads/connector/j/5.1.html
这里用为tomcat配置数据源的方法。在web应用的META-INF文件夹下创建一个context.xml配置文件,并在其中添加<Context>标签进行配置,这种方式生成的数据源只能用于当前web应用.

context.xml注释版(无注释版见下)

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/DBCP_test" docBase="DBCP_test" reloadable="true" crossContext="true" debug = "5">
    path: 即要建立的虚拟目录, 注意是/DBCP_test, 它指定访问Web应用的上下文根,
    如http://localhost:8080/DBCP_test/****
    
    docBase: 为应用程序的路径或WAR文件存放的路径, 可以是绝对路径, 也可是相
    对路径, 相对路径是相对于<Host >
    
    reloadable:如果这个属性设为true, Tomcat服务器在运行状态下会监视在
    WEB-INF/classes和Web-INF/lib目录CLASS文件的改变,
    如果监视到有class文件被更新,服务器自动重新加载Web应用,
    这样我们可以在不重起tomcat的情况下改变应用程序
    
    debug:为设定debug的等级, 程序异常时写入日志文件里的详细程度, 
    0提供最少的信息, 9提供最多的信息,
<Resource
    name="jdbc/mysql" 
    当前创建数据连接池的名字, 由自己定义, 在使用jndi容器获取该数据源对象时会用到
    
    auth="Container"    
    auth:指定管理Resource的Manager,由两个可选值:Container和Application。
    Container表示由容器来创建和管理Resource,Application表示由WEB应用来创建和管理Resource。
    如果在web application deployment descriptor(web.xml)中使用<resource-ref>,这个属性是必需的,
    如果使用<resource-env-ref>,这个属性是可选的。            
                       
    type="javax.sql.DataSource"    
    对象类型固定为DataSource即可 
                     
    maxActive="100"
    连接池支持的最大连接数, 设0为没有限制
    
    maxIdle="30"
    连接池中最多可空闲maxIdle个连接, 设0为没有限制
    
    maxWait="10000"
    连接池中连接用完时,新的请求等待时间,毫秒
   
    username="root"
    数据库连接的用户名
    
    password="123456"
    数据库用户的密码
    
    driverClassName="com.mysql.jdbc.Driver" 
    JDBC的驱动程序
    
    url="jdbc:mysql://localhost:3306/DateBase_Name?autoReconnect=true" />
    数据库URL地址,mysql5以上的,设置autoReconnect=true 是无效的 只有4.x版本,起作用
    autoReconnect=true含义:当数据库连接异常中断时,是否自动重新连接,数据库的url还可
    以携带其他的参数,如:
    url="jdbc:mysql://localhost:3306/DateBase_Name?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"
    后面两个参数的作用是:指定字符的编码、解码格式。在MySQL中,数据库用的是gbk编码,而项目数据库用的是utf-8编码,这两个参数的作用如下:
    1.存数据时:
    数据库在存放项目数据的时候会先用UTF-8格式将数据解码成字节码,然后再将解码后的字节码重新使用GBK编码存放到数据库中。
    2.取数据时:
    在从数据库中取数据的时候,数据库会先将数据库中的数据按GBK格式解码成字节码,然后再将解码后的字节码重新按UTF-8格式编码数据,最后再将数据返回给客户端。
    注意在xml文件中,参数用&amp;隔开
</Context>

context.xml无注释版

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/DBCP_test" docBase="DBCP_test" reloadable="true" crossContext="true" debug = "5">
<Resource
    name="jdbc/mysql" 
    auth="Container"                                  
    type="javax.sql.DataSource"                   
    maxActive="100"
    maxIdle="30"
    maxWait="10000"
    username="root"
    password="123456"
    driverClassName="com.mysql.jdbc.Driver" 
    url="jdbc:mysql://localhost:3306/DateBase_Name?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8" />
</Context>

在tomcat启动时,会逐个加载其中的web应用,当其加载到当前应用时,会加载到META-INF文件夹下该context.xml配置文件,此时tomcat会根据其中的配置信息为当前web应用创建一个数据库连接池,注该数据库连接池只能用于当前web应用,tomcat下的其他web应用无法使用该数据库连接池。Tomcat中有一个共有的容器:jndi,当Tomcat为web应用创建数据源之后会将数据源以键值对的形式存放到jndi容器当中,其中键名就是数据源配置时给定的名字。而Tomcat会自动将jndi容器放到初始化容器InitalContext中,且jndi以固定的名字(java:comp/env)存储在InitalContext容器中。

获取数据库连接池实例步骤(通常将这部分设置为静态块:类加载的时候会执行一次,且只会执行一次(类似与单例模式)):

  1. 获取InitalContext容器实例(JNDI的接口)
    Context initContext = new InitialContext();

  2. 在InitalContext容器中根据字符串java:comp/env搜寻,以及获取jndi容器实例
    Context envContext = (Context)initContext.lookup("java:/comp/env");

  3. 根据数据源(数据库连接池)的名称从jndi容器获取到数据源(数据库连接池)实例,通过JNDI中的核心api(Context),调用该对象的lookup方法,去jdni容器中根据资源的名称来检索一个对象
    ds = (DataSource)envContext.lookup("jdbc/mysql");

进行简单的测试,建立DBCP_Test.jsp文件

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page import="java.sql.*, javax.sql.DataSource,javax.naming.*"%>
<%@ page contentType="text/html; charset=utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
    <%
        try {
            Context initContext = new InitialContext();
            Context envContext = (Context) initContext.lookup("java:/comp/env");
            DataSource ds = (DataSource) envContext.lookup("jdbc/mysql");
            Connection conn = ds.getConnection();
            out.print("连接成功");
            conn.close();
        } catch (Exception e) {
            out.print(e.toString());
        }
    %>
</body>
</html>

运行结果:

注意:context.xml的存放位置不同,它的作用范围也不同。如在tomcat安装目录/conf/context.xml,它的作用范围配置在这个位置的信息将会被所有的web应用所共享。

开发中可使用C3P0、DBCP等开源的数据库连接池以及开源的DBUtils完成增删查改工作,BeanUtils获取Bean减少代码量。

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL数据库连接的配置可以通过以下步骤实现: 1. 在MySQL中创建一个用户,并授权该用户可以访问需要连接数据库。 2. 在Java程序中引入数据库连接的相关依赖,比如常用的Apache Commons DBCP或者HikariCP等。 3. 在Java程序中配置连接参数,比如最大连接数、最小连接数、连接超时时间等。 4. 在Java程序中编写代码,使用连接获取数据库连接,执行SQL语句。 以下是一个简单的MySQL数据库连接配置示例: 1. 创建一个MySQL用户,并授权该用户可以访问需要连接数据库: ``` CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON mydatabase.* TO 'myuser'@'localhost'; ``` 2. 在Java程序中引入数据库连接的相关依赖,比如HikariCP: ``` <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>3.4.5</version> </dependency> ``` 3. 在Java程序中配置连接参数: ``` java HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/mydatabase"); config.setUsername("myuser"); config.setPassword("mypassword"); config.setMaximumPoolSize(10); config.setMinimumIdle(5); config.setConnectionTimeout(30000); ``` 4. 在Java程序中编写代码,使用连接获取数据库连接,执行SQL语句: ``` java try (Connection conn = new HikariDataSource(config).getConnection()) { PreparedStatement statement = conn.prepareStatement("SELECT * FROM mytable"); ResultSet rs = statement.executeQuery(); while (rs.next()) { // 处理查询结果 } } catch (SQLException e) { e.printStackTrace(); } ``` 注意:以上示例仅供参考,具体的配置和使用方式需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值