什么是数据库连接池.docx

上传人:b****5 文档编号:8142995 上传时间:2023-01-29 格式:DOCX 页数:13 大小:21.28KB
下载 相关 举报
什么是数据库连接池.docx_第1页
第1页 / 共13页
什么是数据库连接池.docx_第2页
第2页 / 共13页
什么是数据库连接池.docx_第3页
第3页 / 共13页
什么是数据库连接池.docx_第4页
第4页 / 共13页
什么是数据库连接池.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

什么是数据库连接池.docx

《什么是数据库连接池.docx》由会员分享,可在线阅读,更多相关《什么是数据库连接池.docx(13页珍藏版)》请在冰豆网上搜索。

什么是数据库连接池.docx

什么是数据库连接池

一、数据库连接池

1.什么是连接池

传统的开发模式下,Servlet处理用户的请求,找Dao查询数据,dao会创建与数据库之间的连接,完成数据查询后会关闭数据库的链接。

这样的方式会导致用户每次请求都要向数据库建立链接而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。

假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、宕机。

 

解决方案就是数据库连接池

连接池就是数据库连接对象的一个缓冲池

我们可以先创建10个数据库连接缓存在连接池中,当用户有请求过来的时候,dao不必创建数据库连接,而是从数据库连接池中获取一个,用完了也不必关闭连接,而是将连接换回池子当中,继续缓存

 

使用数据库连接池可以极大地提高系统的性能

 

2.实现数据库连接池

jdbc统一了数据库的操作 定义了规范

jdbc针对数据库连接池也定义的接口java.sql.DataSource,所有的数据库连接池实现都要实现该接口

该接口中定义了两个重载的方法

ConnectiongetConnection()

ConnectiongetConnection(String username,String password)

 

数据库连接池实现思路

1)定义一个类实现java.sql.DataSource接口

2)定义一个集合用于保存Connection对象,由于频繁地增删操作,用LinkedList比较好

3)实现getConnection方法,在方法中取出LinkedList集合中的一个连接对象返回

注意:

  返回的Connection对象不是从集合中获得,而是删除

  用户用完Connection,会调用close方法释放资源,此时要保证连接换回连接池,而不是关闭连接

  重写close方法是难点,解决方案:

装饰设计模式、动态代理

 

二、数据源

通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。

 

一些开源组织提供了数据源的独立实现,常用的有:

DBCP数据库连接池

C3P0数据库连接池

1. DBCP数据源

介绍

DBCP是Apache软件基金组织下的开源连接池实现

tomcat服务器就是使用DBCP作为数据库连接池

使用DBCP数据源,需要导入两个jar包

Commons-dbcp.jar:

连接池的实现

Commons-pool.jar:

连接池实现的依赖库

 

DBCP核心API

BasicDataSource

数据源实现

BasicDataSourceFactory

用于创建数据源的工厂类

 

dbcp创建连接池

方法1:

 直接创建对象,设置参数

BasicDataSourcebds=newBasicDataSource();

 

//设置连接数据库需要的配置信息

bds.setDriverClassName("com.mysql.jdbc.Driver");

bds.setUrl("jdbc:

mysql:

//localhost:

3306/jdbc3");

bds.setUsername("root");

bds.setPassword("root");

 

//设置连接池的参数

bds.setInitialSize(5);

bds.setMaxActive(10);

 

ds=bds

 

方法2:

通过工厂类创建对象,读取配置文件

try{

  Propertiesprop=newProperties();

  //读配置文件

  InputStreamin=

  JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");

  prop.load(in);

  ds=BasicDataSourceFactory.createDataSource(prop);

}catch(Exceptione){

  thrownewExceptionInInitializerError(e);

}

 

配置文件为dbcpconfig.properties

#连接设置

driverClassName=com.mysql.jdbc.Driver

url=jdbc:

mysql:

//localhost:

3306/jdbc3

username=root

password=root

 

#

--初始化连接-->

initialSize=5

 

#最大连接数量

maxActive=10

 

#

--最大空闲连接-->

maxIdle=10

 

 

#

--超时等待时间以毫秒为单位6000毫秒/1000等于60秒-->

maxWait=60000

 

 

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:

[属性名=property;]

#注意:

"user"与"password"两个属性会被明确地传递,因此这里不需要包含他们。

connectionProperties=useUnicode=true;characterEncoding=gbk

 

#指定由连接池所创建的连接的自动提交(auto-commit)状态。

defaultAutoCommit=true

 

#driverdefault指定由连接池所创建的连接的只读(read-only)状态。

#如果没有设置该值,则“setReadOnly”方法将不被调用。

(某些驱动并不支持只读模式,如:

Informix)

defaultReadOnly=

 

#driverdefault指定由连接池所创建的连接的事务级别(TransactionIsolation)。

#可用值为下列之一:

(详情可见javadoc。

)NONE,READ_UNCOMMITTED,READ_COMMITTED,REPEATABLE_READ,SERIALIZABLE

defaultTransactionIsolation=READ_UNCOMMITTED

2. C3P0数据源

介绍

c3p0是一个开源的jdbc连接池,我们熟悉的Hibernate和Sprint框架使用的都是该数据源

 

创建连接池对象

方法1:

直接创建对象,设置参数

ComboPooledDataSourcecpds=newComboPooledDataSource();

cpds.setDriverClass("com.mysql.jdbc.Driver");

cpds.setJdbcUrl("jdbc:

mysql:

//localhost:

3306/jdbc3");

cpds.setUser("root");

cpds.setPassword("root");

cpds.setInitialPoolSize(5);

cpds.setMaxPoolSize(15);

方法2:

读取配置文件

ComboPooledDataSourcecpds=newComboPooledDataSource("itcast");

配置文件为c3p0-config.xml该文件需要放在类路径下

 

  

    

—-默认配置–->

     5

     15

     com.mysql.jdbc.Driver

     jdbc:

mysql:

//localhost:

3306/jdbc3

     root

     root

  

  

     5

     15

     com.mysql.jdbc.Driver

     jdbc:

mysql:

//localhost:

3306/jdbc3

     root

     root

  

 

三、ResultSetMetaData对象

元数据,可以理解为描述数据的数据

jdbc中的元数据是指数据库、表、列的定义信息

 

ResultSetMetaData对象表示结果集ResultSet对象的元数据

获得该对象:

ResultSetMetaDatametaData=rs.getMetaData();

 

常用方法:

getColumnCount() 返回resultset对象的列数

getColumnName(int column) 获得指定列的名称

getColumnTypeName(int column)获得指定列的类型

 

四、jdbc优化

使用jdbc对数据库进行crud操作时,会有很多重复的代码,仔细分析不难发现其实变化的只是其中几行代码

 

对于cud(增删改)操作,代码几乎完全一样,唯一的区别就是sql语句不同,我们完全可以把相同的代码抽取出来定义在一个工具方法中,然后定义一个参数来接收sql语句

 

对于r(查询)操作,除SQL语句不同之外,根据操作的实体不同,对ResultSet结果集的处理也有所不相同,因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中

 

优化后的工具类JdbcUtils

// 通用的增删改方法

public static int update(Stringsql,Object[]params) throws SQLException{

  Connectionconn=null;

  PreparedStatementpstmt= null;

  ResultSetrs= null;

   try {

      // 获得连接

     conn=getConnection();

      // 预编译sql

     pstmt=conn.prepareStatement(sql);

      // 将参数设置进去

      for(int i=0; params!

=null&&i

         pstmt.setObject(i+1,params[i]);

     }

      // 发送sql

      int num=pstmt.executeUpdate();

      return num;

  } finally {

      // 释放资源

     release(conn,pstmt,rs);

  }

}

 

// 优化查询

public static Objectquery(Stringsql,Object[]params,ResultSetHandlerrsh) throws SQLException{

  Connectionconn=null;

  PreparedStatementpstmt= null;

  ResultSetrs= null;

   try {

      // 获得连接

     conn=getConnection();

      // 预编译sql

     pstmt=conn.prepareStatement(sql);

      // 将参数设置进去

      for(int i=0;params!

=null&&i

         pstmt.setObject(i+1,params[i]);

     }

      // 发送sql

     rs=pstmt.executeQuery();

      // 不知道别人想如何处理结果集

      // 干脆想别人所要一个结果集的处理器

      // 为了让当前代码继续,定义一个结果集处理器接口

      // 策略模式,规定算法,具体的算法留给将来的调用者实现

     Objectobj=rsh.handle(rs);

      return obj;

  } finally {

      // 释放资源

     release(conn,pstmt,rs);

  }

}

 

 

结果集处理器接口

publicinterfaceResultSetHandler{

  //处理结果集的方法

  publicObjecthandle(ResultSetrs);

}

 

实现类:

BeanListHandler

publicclassBeanListHandlerimplementsResultSetHandler{

 

  privateClassclazz;

  publicBeanListHandler(Classclazz){

     this.clazz=clazz;

  }

  publicObjecthandle(ResultSetrs){

     try{

         //取出结果集所有的记录,封装到bean,存入list返回

         Listlist=newArrayList();

         while(rs.next()){

            Objectbean=clazz.newInstance();

            //获得元数据

            ResultSetMetaDatametaData=rs.getMetaData();

            //获得列的数量

            intcount=metaData.getColumnCount();

            //遍历列

            for(inti=1;i<=count;i++){

               //取列名

               StringcolumnName=metaData.getColumnName(i);

               //取这列的值

               Objectvalue=rs.getObject(columnName);

               //反射出属性

               Fieldfield=clazz.getDeclaredField(columnName);

               //设置属性

               field.setAccessible(true);

               field.set(bean,value);

            }

            //加入list

            list.add(bean);

         }

         returnlist;

     }catch(Exceptione){

         thrownewRuntimeException(e);

     }

  }

 

}

 

BeanHandler

publicclassBeanHandlerimplementsResultSetHandler{

  privateClassclazz;

  publicBeanHandler(Classclazz){

     this.clazz=clazz;

  }

  publicObjecthandle(ResultSetrs){

     //不知道有几列数据,不知道列名,不知道封装到什么样的bean

     //表的列明和javabean的字段名一致

     try{

         if(rs.next()){

            //创建bean

            Objectbean=clazz.newInstance();

            //封装数据

            //获得结果集的元数据

            ResultSetMetaDatametaData=rs.getMetaData();

            intcount=metaData.getColumnCount();

            //迭代取每一列的数据

            for(inti=1;i<=count;i++){

               //获得列名 username

               StringcolumnName=metaData.getColumnName(i);

               //获得数据ddd

               Objectvalue=rs.getObject(columnName);

               //根据列名反射出映射的属性username

               Fieldfield=clazz.getDeclaredField(columnName);

               //为属性赋值

               field.setAccessible(true);

               field.set(bean,value);

            }

            returnbean;

         }

         returnnull;

     }catch(Exceptione){

         thrownewRuntimeException(e);

     }

  }

 

}

 

ArrayHandler

//取出第一行的所有记录存入一个Object数组

publicclassArrayHandlerimplementsResultSetHandler{

 

  publicObjecthandle(ResultSetrs){

     try{

         if(rs.next()){

            //指向了第一行的记录

            //获得元数据

            ResultSetMetaDatametaData=rs.getMetaData();

            //获得列数

            intcount=metaData.getColumnCount();

            //创建数组

            Object[]arr=newObject[count];

            //迭代所有列的值,存入数组

            for(inti=1;i<=count;i++){

               Objectvalue=rs.getObject(i);//获得指定列的值

               arr[i-1]=value;

            }

            returnarr;

         }

         returnnull;

     }catch(Exceptione){

         thrownewRuntimeException(e);

     }

  }

 

}

 

批处理

 

处理大数据

ClobCharacterlargeObject

text

 

Blobbinary largeobject

 

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 小升初

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1