快盘下载:好资源、好软件、快快下载吧!

快盘排行|快盘最新

当前位置:首页软件教程电脑软件教程 → 什么是JDBC、JNDI和DBCP以及DataSource?

什么是JDBC、JNDI和DBCP以及DataSource?

时间:2022-09-16 09:11:23人气:作者:快盘下载我要评论

什么是JDBC、JNDI和DBCP以及DataSource?

JDBC:Java DataBase Connectivity,Java连接数据库和执行SQL语句的API。

JNDI:Java Naming and Directory Interface,Java命名和目录接口。JNDI是指使用数据源连接数据库的这种方式,简单地,可以将JNDI理解为所有Data Source的集合。

DBCP:DataBase Connection Pool,数据库连接池。数据连接池就是连接数据库的进程的集合。一般的SQL 执行都是“建立数据库连接--执行SQL--关闭数据库连接”,对于频繁连接数据库应用,这样反复“建立连接--关闭连接”是非常耗系统资源的。

Data Source:数据源。就是将IP、数据库、用户名、密码封装起来对外只提供一个JNDI名称,在应用中只要调用这个JNDI就能连接数据库,而不需要在代码中写入用户名密码等信息。这样做的好处是,当用户名密码乃至数据库变化时只需要去修改JNDI的xml文件而不需要去修改代码。

数据源、JNDI、DBCP都是在中间件配置维护而不是在应用代码中配置维护的。

Java连接mysql用DBCP连接池的实现:

https://www.cnblogs.com/sunseine/p/5947448.html

0、DBCP简介

DBCP(DataBase connection pool)数据库连接池是 apache 上的一个Java连接池项目。DBCP通过连接池预先同数据库建立一些连接放在内存中(即连接池中),应用程序需要建立数据库连接时直接到从接池中申请一个连接使用,用完后由连接池回收该连接,从而达到连接复用,减少资源消耗的目的。

1、DBCP所依赖的jar包(以下例子基于如下jar包版本)

  commons-dbcp2-2.1.1.jar commons-logging-1.2.jar commons-pool2-2.4.2.jar

2、DBCP使用示例

下图是在Eclipse中创建的Java工程,使用了DBCP相关的jar包,mysql的jdbc驱动jar包,junit4 。

   并在src同级目录下创建了config目录,用于存放DBCP的配置文件。

【注】类DBCPUtil.java在下面的例子中未用到。

Java

1) DBCP配置文件dbcp.properties

########DBCP配置文件##########
#驱动名
driverClassName=com.mysql.jdbc.Driver
#url
url=jdbc:mysql://127.0.0.1:3306/mydb
#用户名
username=sa
#密码
password=123456
#初试连接数
initialSize=30
#最大活跃数
maxTotal=30
#最大idle数
maxIdle=10
#最小idle数
minIdle=5
#最长等待时间(毫秒)
maxWaitMillis=1000
#程序中的连接不使用后是否被连接池回收(该版本要使用removeAbandonedOnMaintenance和removeAbandonedOnBorrow)
#removeAbandoned=true
removeAbandonedOnMaintenance=true
removeAbandonedOnBorrow=true
#连接在所指定的秒数内未使用才会被删除(秒)(为配合测试程序才配置为1秒)
removeAbandonedTimeout=1

2) 创建初始化DBCP的类KCYDBCPUtil.java  

package dbcp;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSourceFactory;

/**
 * DBCP配置类
 * @author SUN
 */
public class KCYDBCPUtil {
    
    private static Properties properties = new Properties();
    private static DataSource dataSource;
    //加载DBCP配置文件
    static{
        try{
            FileInputStream is = new FileInputStream("config/dbcp.properties");  
            properties.load(is);
        }catch(IOException e){
            e.printStackTrace();
        }
        
        try{
            dataSource = BasicDataSourceFactory.createDataSource(properties);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    
    //从连接池中获取一个连接
    public static Connection getConnection(){
        Connection connection = null;
        try{
            connection = dataSource.getConnection();
        }catch(SQLException e){
            e.printStackTrace();
        }
        try {
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
    
    public static void main(String[] args) {
        getConnection();
    }
}

3) 创建使用JDBC获取数据库连接的类DBConn.java(用于和DBCP连接池对比)

package dbcp;

import java.sql.Connection;
import java.sql.DriverManager;

public class DBConn {
    private static Connection conn = null;
    
    //获取一个数据库连接
    public static Connection getConnection() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            String dbUrl = "jdbc:mysql://127.0.0.1:3306/mydb";
            conn = DriverManager.getConnection(dbUrl, "sa", "123456");
//            System.out.println("========数据库连接成功========");
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("========数据库连接失败========");
            return null;
        }
        return conn;
    }
}

4) 创建测试类DBCPTest.java

    测试类中采用3中方法将2000个数据插入数据库同一张表中,每次插入数据之前,先清空表,并对结果进行了对比。

    3中插入数据方法如下:

    (1) 每次插入一条数据前,就创建一个连接,该条数据插入完成后,关闭该连接;

   (2) 使用DBCP连接池,每次插入一条数据前,从DBCP连接池中获取一条连接,该条数据插入完成后,该连接交由DBCP连接池管理;

    (3) 在插入数据之前创建一条连接,2000个数据全部使用该连接,2000个数据插入完毕后,关闭该连接。

package dbcp;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Test;

public class DBCPTest {
    
    //测试,每写一条数据前,就新建一个连接
    @Test
    public void testWriteDBByEveryConn() throws Exception{
        for(int i = 0; i < 2000; i++){
            writeDBByEveryConn(i);
        }
        System.out.println("DONE");
        
    }
    
    //测试,使用连接池,每写一条数据前,从连接池中获取一个连接
    @Test
    public void testWriteDBByDBCP() throws Exception{
        for(int i = 0; i < 2000; i++){
            writeDBByDBCP(i);
        }
        System.out.println("DONE");
    }
    
    //测试,只建一条连接,写入所有数据
    @Test
    public void testWriteDBByOneConn() throws Exception{
        Connection conn = DBConn.getConnection();
        Statement stat = conn.createStatement();
        for(int i = 0; i < 2000; i++){
            writeDBByOneConn(i, stat);
        }
        conn.close();
        System.out.println("DONE");
    }
    
    //不使用连接池写数据库,每写一条数据创建一个连接
    public void writeDBByEveryConn(int data){
        String sql = "insert into dbcp values (" + data + ")"; 
        Connection conn = DBConn.getConnection();
        try{    
            Statement stat = conn.createStatement();
            stat.executeUpdate(sql);            
        }catch(Exception e){
            e.printStackTrace() ;
        }finally{
            try {    
                conn.close();    
            } catch (SQLException e) {
                e.printStackTrace();
            }
            
        }
    }
    
    //不使用连接池写数据库,只用一个连接,写所有数据
    public void writeDBByOneConn(int data, Statement stat){
        String sql = "insert into dbcp values (" + data + ")"; 
        try{    
            stat.executeUpdate(sql);            
        }catch(Exception e){
            e.printStackTrace() ;
        }
    }
    
    //通过DBCP连接池写数据库
    public void writeDBByDBCP(int data){ 
        String sql = "insert into dbcp values (" + data + ")"; 
        try {
            Connection conn = KCYDBCPUtil.getConnection();  
            Statement stat = conn.createStatement();
            stat.executeUpdate(sql);
            conn.commit();
            conn.close();
        } catch (SQLException e) {   
            e.printStackTrace();  
        }
    }

}

测试结果如下:

  (1) 每次插入一条数据前,就创建一个连接,该条数据插入完成后,关闭该连接。耗时158.318秒

SQL

  (2) 使用DBCP连接池,每次插入一条数据前,从DBCP连接池中获取一条连接,该条数据插入完成后,该连接交由DBCP连接池管理。耗时122.404秒

Java

  (3) 在插入数据之前创建一条连接,2000个数据全部使用该连接,2000个数据插入完毕后,关闭该连接。耗时117.87秒

JAR

  通过对比结果看出,向同一个表中插入2000条数据,每插入一条数据前创建一个新连接,会非常耗时,而使用DBCP连接池和使用同一个连接操作,耗时比较接近。

3、相关问题

1) 应用程序中,使用完一个数据库连接后,DBCP连接池如何管理该连接。

   分两种情况:

    (1) 应用程序中主动关闭该连接,即DBCPTest.java中第79行 conn.close();

     这种情况并不是手动将该连接关闭,而是将该连接交回给DBCP连接池,由连接池管理该连接。即用完连接后显示的将数据库连接提交至DBCP连接池。

    (2) 应用程序中不关闭该连接,即将DBCPTest.java中第79行 conn.close()注释掉

     这种情况DBCP配置文件dbcp.properties中的配置项(注意jar包版本,低版本中使用removeAbandoned=true配置项) 

     removeAbandonedOnMaintenance=true    removeAbandonedOnBorrow=true      removeAbandonedTimeout=1

会起作用, 表示DBCP连接池自动管理应程序中使用完毕的连接, 表示一个连接在程序中使用完毕后,若在1秒之内没有再次使用,则DBCP连接池回收该连接(通常removeAbandonedTimeout不会配置1,此处为了测试使用)。

    (3) 验证 和 配置项的作用

     将测试类DBCPTest.java的writeDBByDBCP(int data)方法修改为如下:

//通过DBCP连接池写数据库
    public void writeDBByDBCP(int data){ 
        String sql = "insert into dbcp values (" + data + ")"; 
        try {
            Connection conn = KCYDBCPUtil.getConnection();  
            Statement stat = conn.createStatement();
            stat.executeUpdate(sql);
            conn.commit();
//            conn.close();
        } catch (SQLException e) {   
            e.printStackTrace();  
        }
    }

    重新执行testWriteDBByDBCP()方法,结果如下:

JAR

    可见writeDBByDBCP(int data)方法修改后和修改前作用相同,说明连接使用完后,由DBCP连接池管理。

    而如果将修改配置项 ,即一个连接用完后会等待180秒,超过180秒后才由DBCP连接池回收,重新执行testWriteDBByDBCP()方法,执行一段时间后报错(Cannot get a connection, pool error Timeout waiting for idle object),如下:

数据库

    此时,查询数据表,发现正好插入了30条数据,如下:

数据库

    这说明在插入第31条数据的时候报错,错误原因是连接池中没有可用的连接了。这是因为DBCP连接池初始化连接数为30, 设为180秒,所以30个连接用完后,程序运行还未 到180秒,程序中用完的连接都还没有被DBCP连接池回收,所以DBCP连接池中没有可用的连接了,才会在插入第31条数据时报错。

相关文章

  • 一步步带你设计MySQL索引数据结构

    一步步带你设计MySQL索引数据结构,想想我们生活中的例子,比如新华字典,我们有一个目录,目录根据拼音排序,内容包含了汉字位于字典中具体的的页码。聪明的你肯定也想到了,我们也可以借鉴这种思想,建立一个MySQL的目录,叫做“索引”。...
  • 影刀连接Mysql数据库

    影刀连接Mysql数据库,影刀配置连接mysql数据库基础版...

网友评论

快盘下载暂未开通留言功能。

关于我们| 广告联络| 联系我们| 网站帮助| 免责声明| 软件发布

Copyright 2019-2029 【快快下载吧】 版权所有 快快下载吧 | 豫ICP备10006759号公安备案:41010502004165

声明: 快快下载吧上的所有软件和资料来源于互联网,仅供学习和研究使用,请测试后自行销毁,如有侵犯你版权的,请来信指出,本站将立即改正。