JavaWeb学习总结(十三)--数据库连接池
一、数据库连接池的概念
用池来管理Connection,这可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了。
JDBC数据库连接池接口(DataSource)
Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商可以让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
开源数据库连接池
现在很多WEB服务器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的实现,即连接池的实现。通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。
也有一些开源组织提供了数据源的独立实现:
- DBCP 数据库连接池
- C3P0 数据库连接池
在使用了数据库连接池之后,在项目的实际开发中就不需要编写连接数据库的代码了,直接从数据源获得数据库的连接。
JDBC数据库连接池接口(DataSource)
Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商可以让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
二、DBCP
DBCP是Apache提供的一款开源免费的数据库连接池!Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。Hibernate3.0之后不再对DBCP提供支持!因为Hibernate声明DBCP有致命的缺欠!
需要应用程序应在系统中增加如下两个 jar 文件:
- Commons-dbcp.jar:连接池的实现
- Commons-pool.jar:连接池实现的依赖库
实现DBCP
1. 加入jar包
2.编写dbcpconfig.properties
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/testdb
username=root
password=123456 #<!-- 初始化连接 -->
initialSize=10 #最大连接数量
maxActive=50 #<!-- 最大空闲连接 -->
maxIdle=20 #<!-- 最小空闲连接 -->
minIdle=5 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8 #指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true #driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=false #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=REPEATABLE_READ
如下图所示:
3、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池
package cn.zy.utils; import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory; /*
* 数据库连接工具类DBCP
*/
public class JdbcUtils_DBCP {
/*
* 在java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现
* DBCP连接池就是javax.sql.DataSource接口的一个具体实现
*/
private static DataSource ds =null;
//在静态代码块中创建数据库连接池
static {
try {
//加载配置文件
InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
prop.load(in);
//创建数据源
ds = BasicDataSourceFactory.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();
}catch (Exception e){
e.printStackTrace();
}
if(st!=null){
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
测试连接
package cn.zy.test; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import org.junit.Test; import cn.zy.utils.JdbcUtils_DBCP; /*
* 测试DBCP数据源
*/
public class DbcpTest {
@Test
public void dbcpDataSourceTest(){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
//获取数据库连接
conn = JdbcUtils_DBCP.getConnection();
String sql = "insert into account(name,money) values(?,?)";
st = conn.prepareStatement(sql);
st.setString(1, "D");
st.setFloat(2, 2000);
st.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
JdbcUtils_DBCP.release(conn, st, rs);
}
} }
三、C3P0数据源
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。
- dbcp没有自动回收空闲连接的功能
- c3p0有自动回收空闲连接功能
在应用程序中加入C3P0连接池
1.导入相关jar包
c3p0-0.9.2-pre1.jar、mchange-commons-0.2.jar,如果操作的是Oracle数据库,那么还需要导入c3p0-oracle-thin-extras-0.9.2-pre1.jar
2、在src下加入C3P0的配置文件:c3p0-config.xml,注意:
配置文件要求:
l 文件名称:必须叫c3p0-config.xml
l 文件位置:必须在src下
c3p0-config.xml的配置信息如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--
c3p0-config.xml必须位于类路径下面
private static ComboPooledDataSource ds;
static{
try {
ds = new ComboPooledDataSource("MySQL");
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
--> <c3p0-config>
<!--
C3P0的缺省(默认)配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源
-->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/testdb</property>
<property name="user">root</property>
<property name="password">123456</property> <property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config> <!--
C3P0的命名配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源
-->
<named-config name="MySQL">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/testdb</property>
<property name="user">root</property>
<property name="password">123456</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>
如图:
3、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池
package cn.zy.utils; import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; /*
* 数据库连接工具类
*/
public class JdbcUtils_C3P0 {
private static ComboPooledDataSource dataSource = null;
//在静态块中创建数据库连接池
static{
try {
//通过代码创建数据库连接池
/*ds = new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/testdb");
ds.setUser("root");
ds.setPassword("123456");
ds.setInitialPoolSize(10);
ds.setMinPoolSize(5);
ds.setMinPoolSize(20);*/ //通过读取xml来获取数据源
//ds = new ComboPooledDataSource();//使用C3P0的默认配置来创建数据源
dataSource = new ComboPooledDataSource("MySQL");//使用C3P0的命名配置来创建数据源
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
} /*
* 从数据源中获取数据库连接
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
} /*
* 返回连接池
*/
public static DataSource getDataSource() {
return dataSource;
}
/*
* 释放资源
*/
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
//关闭存储查询结果的ResultSet对象
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
//关闭负责执行SQL命令的Statement对象
st.close();
}catch (Exception e) {
e.printStackTrace();
}
} if(conn!=null){
try{
//将Connection连接对象还给数据库连接池
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
编写测试类:
package cn.zy.test; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import org.junit.Test; import cn.zy.utils.JdbcUtils_C3P0; public class C3p0Test {
@Test
public void fun(){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils_C3P0.getConnection();
String sql = "insert into account(name,money) values(?,?)";
st = conn.prepareStatement(sql);
st.setString(1, "F");
st.setFloat(2,3000);
st.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、配置Tomcat数据源
在实际开发中,我们有时候还会使用服务器提供给我们的数据库连接池,比如我们希望Tomcat服务器在启动的时候可以帮我们创建一个数据库连接池,那么我们在应用程序中就不需要手动去创建数据库连接池,直接使用Tomcat服务器创建好的数据库连接池即可。要想让Tomcat服务器在启动的时候帮我们创建一个数据库连接池,那么需要简单配置一下Tomcat服务器。
4.1 Tomcat配置JNDI资源
JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包,
这 套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需 通过名称检索即可。其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象。
Tomcat服务器创建的数据源是以JNDI资源的形式发布的,所以说在Tomat服务器中配置一个数据源实际上就是在配置一个JNDI资源,通过查看Tomcat文档,我们知道使用如下的方式配置tomcat服务器的数据源:
<Context>
<Resource name="jdbc/datasource" auth="Container"
type="javax.sql.DataSource" username="root" password="123456"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/testdb"
maxActive="8" maxIdle="4"/>
</Context>
服务器创建好数据源之后,我们的应用程序又该怎么样得到这个数据源呢,Tomcat服务器创建好数据源之后是以JNDI的形式绑定到一个JNDI容器中的,我们可以把JNDI想象成一个大大的容器,我们可以往这个容器中存放一些对象,一些资源,JNDI容器中存放的对象和资源都会有一个独一无二的名称,应用程序想从JNDI容器中获取资源时,只需要告诉JNDI容器要获取的资源的名称,JNDI根据名称去找到对应的资源后返回给应用程序。我们平时做javaEE开发时,服务器会为我们的应用程序创建很多资源,比如request对象,response对象,服务器创建的这些资源有两种方式提供给我们的应用程序使用:第一种是通过方法参数的形式传递进来,比如我们在Servlet中写的doPost和doGet方法中使用到的request对象和response对象就是服务器以参数的形式传递给我们的。第二种就是JNDI的方式,服务器把创建好的资源绑定到JNDI容器中去,应用程序想要使用资源时,就直接从JNDI容器中获取相应的资源即可。
对于上面的name="jdbc/datasource"数据源资源,在应用程序中可以用如下的代码去获取
1 Context initCtx = new InitialContext();
2 Context envCtx = (Context) initCtx.lookup("java:comp/env");
3 dataSource = (DataSource)envCtx.lookup("jdbc/datasource");
此种配置下,数据库的驱动jar文件需放置在tomcat的lib下
4.2、配置Tomcat数据源
1、在Web项目的WebRoot目录下的META-INF目录创建一个context.xml文件
2、在Web项目的WebRoot目录下的META-INF目录创建一个context.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource
name="jdbc/datasource"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="123456"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/testdb"
maxActive="8"
maxIdle="4"/>
</Context>
3、将数据库的驱动jar文件需放置在tomcat的lib下
4、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中获取JNDI容器中的数据源
package cn.zy.utils; import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource; public class JdbcUtils_JNDI {
private static DataSource ds = null;
//在静态代码块中创建数据库连接池
static{
try {
//初始化JNDI
Context initCtx = new InitialContext();
//得到JNDI容器
Context envCtx = (Context) initCtx.lookup("java:comp/env");
//从JNDI容器中检索name为jdbc/datasource的数据源
ds = (DataSource)envCtx.lookup("jdbc/datasource");
} 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();
}catch (Exception e){
e.printStackTrace();
}
if(st!=null){
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
写一个Servlet进行测试:
package cn.zy.test; import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import cn.zy.utils.JdbcUtils_JNDI; public class JNDITest extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
//获取连接
conn = JdbcUtils_JNDI.getConnection();
String sql = "insert into account(name,money) values(?,?)";
st = conn.prepareStatement(sql);
st.setString(1, "F");
st.setFloat(2, 2000);
st.executeUpdate();
response.getWriter().print("插入成功");
} catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils_JNDI.release(conn, st, rs);
} } public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }
JavaWeb学习总结(十三)--数据库连接池的更多相关文章
- (转)JavaWeb学习总结(十三)——使用Session防止表单重复提交
如何防止表单重复提交 在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复 ...
- JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)
JDBC数据库连接池的必要性 一.在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤: 1)在主程序(如servlet/beans)中建立数据库连接 2)进行sql操作 3)断开数据库连接 ...
- JDBC 学习复习6 学习与编写数据库连接池
之前的工具类DBUtil暴露的问题 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的 ...
- 【转】JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)
转自:http://www.cnblogs.com/ysw-go/ JDBC数据库连接池的必要性 一.在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤: 1)在主程序(如servlet/ ...
- JDBC编程学习笔记之数据库连接池的实现
在JDBC编程的时候,获取到一个数据库连接资源是很宝贵的,倘若数据库访问量超大,而数据库连接资源又没能得到及时的释放,就会导致系统的崩溃甚至宕机.造成的损失将会是巨大的.再看有了数据库连接池的JDBC ...
- javaweb(三十九)——数据库连接池
一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...
- javaweb基础(39)_数据库连接池
一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...
- Go组件学习——database/sql数据库连接池你用对了吗
1.案例 case1: maxOpenConns > 1 func fewConns() { db, _ := db.Open("mysql", "root:roo ...
- javaWeb代码整理03-druid数据库连接池
jar包: maven坐标: <dependency> <groupId>com.alibaba</groupId> <artifactId>druid ...
- java学习笔记—第三方数据库连接池包1(29)
第一步:导入dbcp包 第二步:通过核心类连接数据 BasicDataSource它是javax.sql.DataSrouce的子类. 一个工具类:BasicDataSourceFactory. 手工 ...
随机推荐
- JavaScript中创建类,赋值给ajax中的data参数
缘由:因为要给根据是否选中checkbox来动态增加ajax中data的属性(ajax的data属性格式的几种方法,参考http://www.jb51.net/article/46676.htm) d ...
- Wampserver3.0.0设置语言为中文无效
打开配置文件"wampmanager.conf",将language改成chinese,再从右键的语言选择中选中文. 这个配置文件有两个,改第一个双引号里的,第二个没有引号的不要改 ...
- HashMap, HashTable, CurrentHashMap的区别
转载:http://www.jianshu.com/p/c00308c32de4 HashMap vs ConcurrentHashMap 引入ConcurrentHashMap是为了在同步集合Has ...
- HDU 4910 Problem about GCD 找规律+大素数判断+分解因子
Problem about GCD Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- java 学习路线《转》
*第一阶段:Java基础,包括java语法,面向对象特征,常见API,集合框架: *第二阶段:java界面编程,包括AWT,事件机制,SWING,这个部分也可以跳过,用的时候再看都能来及: *第三阶段 ...
- DLL数据共享在不同处定义效果不同..
DLL头文件: #ifndef _DLL_SAMPLE_H #define _DLL_SAMPLE_H #pragma data_seg("ShareReadAndWrite") ...
- noip2011提高组day1+day2解题报告
Day1 T1铺地毯https://www.luogu.org/problem/show?pid=1003 [题目分析] 全部读入以后从最后一个往前找,找到一个矩形的范围覆盖了这个点,那这个矩形就是最 ...
- Xcode关闭ARC
开启了ARC则不能显示调用dealloc/retain/release等手动内存管理操作,所以很多情况下需要关闭. Xcode中有两种途径可以关闭ARC. 1.创建项目时将ARC选项的勾取消掉. 2. ...
- 在WIn32程序中使用MFC的CInternetSession运行异常,主要是因为获取目前应用程序名出错的解决办法
转载:http://group.gimoo.net/review/22564 头文件#include <afxinet.h"> 在非MFC工程中使用CInternetSessio ...
- CoreData 与 SQLite 比较
CoreData.framework : iOS中提供了对原始SQLite数据库API访问的封装,通过这个framework来管理数据缓存和持久数据要比使用SQL语句操作SQLite数据库简单和方便许 ...