数据库连接池
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库连接池相关的知识,希望对你有一定的参考价值。
手动编写连接池需实现java.sql.DataSource接口。DataSource接口中定义了两个重载的getConnection方法:(JDK API)
Connection getConnection()
Connection getConnection(String username, String password)
实现DataSource接口,并实现连接池功能的步骤:
1. 在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加入LinkedList对象中。
2. 实现getConnection方法,让getConnection方法每次调用时,从LinkedList中取一个Connection返回给用户。
3. 当用户使用完Connection,调用Connection.close()方法时,Collection对象应保证将自己返回到LinkedList中,而不要把conn还给数据库。
4. Collection保证将自己返回到LinkedList中是此处编程的难点。
所以为了让连接用完返回给LinkedList集合,而不是返还给数据库,必须要增强connection的close方法
//增强 close方法,conn.close()
在实际开发,发现对象的方法满足不了开发需求时,有三种方式对其进行增强
1.写一个connecton子类,覆盖close方法,增强close方法
2.用包装设计模式
3.用动态代理 aop 面向切面编程
这里不可以用子类的方法来做,因为connection里面封装了很多其他信息,程序中还会用到connection的其他信息,所以如果用子类的方法基本不可能,等同于要重新写jdbc的驱动了。
包装设计模式增强close方法步骤:
1.定义一个类,实现与被增强相同的接口
2.在类中定义一个变量,记住被增强对象
3.定义一个构造函数,接收被增强对象
4.覆盖想增强的方法
5.对于不想增强的方法,直接调用目标对象(被增强对象)的方法
class MyConnection implements Connection{ private Connection conn; public MyConnection(Connection conn){ this.conn = conn; } public void close(){ list.add(this.conn); } public void clearWarnings() throws SQLException { this.conn.clearWarnings(); }
.......
最好的解决办法是动态代理。采用拦截技术。AOP,面向切面编程
开源数据库连接池:数据库连接池也叫数据源
现在很多WEB服务器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的实现,即连接池的实现。
通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。
也有一些开源组织提供了数据源的独立实现:
DBCP 数据库连接池
C3P0 数据库连接池
实际应用时不需要编写连接数据库代码,直接从数据源获得数据库的连接。程序员编程时也应尽量使用这些数据源的实现,以提升程序的数据库访问性能。
TOMCAT内置的连接池就是DBCP,tomcat是Apache的,dbcp也是apache的。
DBCP数据源:
DBCP 是 Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:
Commons-dbcp.jar:连接池的实现
Commons-pool.jar:连接池实现的依赖库
Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
dbcpconfig.properties封装了DBCP数据源的一些配置信息,包括数据库连接,连接数等。
一般放在src文件夹下
public class JdbcUtils_DBCP { private static DataSource ds = null; static{ try{ InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); Properties prop = new Properties(); prop.load(in); BasicDataSourceFactory factory = new BasicDataSourceFactory(); ds = factory.createDataSource(prop); }catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException{ return ds.getConnection();//从连接池中拿连接,这个连接肯定也是增强过的,因为该连接用完还要还给连接池。 } public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{ rs.close(); //throw new }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } st = null; } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } } }
在开发中可以通过上面的连接池来获取连接,释放连接。
C3P0数据源:Spring内置的连接池就是C3P0
导入C3P0的两个jar包
c3p0.....jar
mchang-commons.jar
c3p0-config.xml 连接池的配置文件,一般放在src目录下,详情查看c3p0的文档
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </default-config> <named-config name="flx"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </named-config> </c3p0-config>
public class JdbcUtils_C3P0 { private static ComboPooledDataSource ds = null; static{ try{ ds = new ComboPooledDataSource(); }catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException{ return ds.getConnection(); } public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{ rs.close(); //throw new }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } st = null; } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } } }
配置TOMCAT数据库连接池:
使用tomcat的时候,可以不必要加入第三方连接池,tomcat内置了一个连接池, 如果希望tomcat
为你的应用程序创建连接池,需要对tomcat做配置。
<Context> <Resource name="jdbc/datasource" auth="Container" type="javax.sql.DataSource" username="root" password="root" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/jdbc" maxActive="8" maxIdle="4"/> </Context>
只要对tomcat做了上面的配置,tomcat启动的时候就会为你的应用程序创建连接池,并且tomcat会把创建的连接池以JNDI的形式绑定到一个uri上面去,
name="jdbc/datasource",只要用的时候使用这个名称在JNDI中检索就可以啦。
以上配置可以在tomcat-config里的server.xml里
也可以在WebRoot-META-INF文件夹下新建一个context.xml里配置
可以参考tomcat的主页里的JNDI-COnfigration
在程序中就可以使用JNDI的方式去向连接池要连接了。
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
dataSource = (DataSource)envCtx.lookup("jdbc/datasource");
特别提醒:此种配置下,驱动jar文件需放置在tomcat的lib下
JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包,
这套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需通过名称检索即可。
其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象。
public class JdbcUtils_Tomcat { private static DataSource ds; static { try { Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); ds = (DataSource) envCtx.lookup("jdbc/EmployeeDB"); } catch (Exception e) { throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException{ return ds.getConnection(); } }
在程序中就可以使用上面的工具类来向tomcat内置的数据源要连接。
以上是关于数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章
newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段
连接池报错 Proxool Provider unable to load JAXP configurator file: proxool.xml
MySQL与Redis数据库连接池介绍(图示+源码+代码演示)