首先一句话说清为什么要引入连接池呢?
传统的jdbc操作数据库步骤就是:
- 建立数据库连接
- 增删改查数据
- 关闭数据库连接
分析这个过程对资源的损耗:服务器连接数据库是类似于socket通信的连接方式,连接速度慢,最后又关闭了连接,下次操作又需要重新建立连接,一会儿连接,一会儿关闭,资源造成了巨大的烂费!因此引入数据源(连接池)。
连接池的核心:将连接的指向改了,现在是指向数据源,而不是数据库。
手写简单连接池底层源码
package pool;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import core.DBManager;
/**
* 连接池的类
* @author john
*
*/
public class DBConnPool {
/**
* 连接池对象
*/
private static List<Connection> pool;
/**
* 最大连接个数
*/
private static final int POOL_MAX_SIZE=DBManager.getConf().getPoolMaxSize();
/**
* 最小连接数
*/
private static final int POOL_MIN_SIZE=DBManager.getConf().getPoolMinSize();
/**
* 初始化连接池、使池中的连接数达到最小值
*/
public void initPool(){
if(pool==null){
pool=new ArrayList<Connection>();
}
while(pool.size()<DBConnPool.POOL_MIN_SIZE){
pool.add(DBManager.creatConn());
//System.out.println("初始化池,池中连接数:"+pool.size());
}
}
/**
* 从连接池中取出一个连接
* 注意:连接池是否为空
* @return
*/
public synchronized Connection getConnection(){
if(pool.isEmpty()==false){
int last_index=pool.size()-1;
Connection conn=pool.get(last_index);
pool.remove(last_index);
return conn;
}else{
return DBManager.creatConn();
}
}
/**
* 将连接放回连接池中
* 注意:连接池中连接数超过最大就真的关闭
* @param conn
*/
public synchronized void close(Connection conn){
if(pool.size()>POOL_MAX_SIZE){
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}else{
pool.add(conn);
}
}
public DBConnPool(){
initPool();
}
}
常见连接池:Tomcat-dbcp、dbcp、c3p0、druid(略)
Tomcat-dbcp连接池(以mysql为例):
a.配置数据源:数据库连接池,位置:/conf/context.xml(类似于JNDI)
<Resource name="student" auth="Container" type="javax.sql.DataSource"
maxActive="400"
maxIdle="20" maxWait="5000" username="root" password="123456"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/student" />
b.在web.xml中指定数据源 :
<resource-ref>
<res-ref-name>student</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
c.使用数据源 (注意:这里要知道数据源(DataSource) 是用来管理数据库连接池的即可)
传统的Connection的获取方式(JDBC操作):
connection = DriverManager.getConnection(URL,USERNAME,PASSWORD);
数据源方式:
Context ctx = new InitialContext() ;//context.xml
DataSource ds = (DataSource)ctx.lookup("java:comp/env/student") ;
connection = ds.getConnection();//ds.getConnection()就是 数据源(连接池)
dbcp连接池(以oracle为例):
a.引入jar包(commons-dbcp-1.4.jar、commons-pool.jar)
b.两种创建数据源方式
1)BasicDataSource方式(硬编码)
//获取dbcp方式的ds对象
public static DataSource getDataSourceWIthDBCP(){
BasicDataSource dbcp = new BasicDataSource();
dbcp.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dbcp.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
dbcp.setUsername("scott");
dbcp.setPassword("tiger");
dbcp.setInitialSize(20);
dbcp.setMaxActive(10);
return dbcp;
}
2)BasicDataSourceFactory方式(配置方式):.properties文件, 编写方式key=value
//配置文件:dbcpconfig.properties
driverClassName=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:ORCL
username=scott
password=tiger
initialSize=10
public static DataSource getDataSourceWIthDBCPByProperties() throws Exception{
DataSource dbcp = null ;
Properties props = new Properties();
//将字符串变成输入流
InputStream input = new DBCPDemo().getClass().getClassLoader().getResourceAsStream("dbcpconfig.properties");
//加载配置文件
props.load( input );
//只需要记住以下一句
dbcp = BasicDataSourceFactory.createDataSource(props ) ;
return dbcp;
}
c3p0连接池(以oracle为例):
a.导入jar包 (c3p0.jar c3p0-oracle-thin-extras.jar)
b.两种创建数据源方式
1)无参,硬编码
public static DataSource getDataSourceWithC3P0(){
ComboPooledDataSource c3p0 = new ComboPooledDataSource();
try {
c3p0.setDriverClass("oracle.jdbc.driver.OracleDriver");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
c3p0.setJdbcUrl("jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
c3p0.setUser("scott");
c3p0.setPassword("tiger");
return c3p0 ;
}
2)有参,配置文件(c3p0-config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<!-- 如果要研究某个xml中可以设置哪些属性。找相关类的 属性 或者setXxx()-->
<property name="user">scott</property>
<property name="password">tiger</property>
<property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
<property name="jdbcUrl">jdbc:oracle:thin:@127.0.0.1:1521:ORCL</property>
<property name="checkoutTimeout">30000</property>
</default-config>
<named-config name="yanqun">
<property name="user">scott</property>
<property name="password">tiger</property>
<property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
<property name="jdbcUrl">jdbc:oracle:thin:@127.0.0.1:1521:ORCL</property>
<property name="checkoutTimeout">20000</property>
</named-config>
</c3p0-config>
public static DataSource getDataSourceWithC3P0ByXml(){
ComboPooledDataSource c3p0 = new ComboPooledDataSource("yanqun");
return c3p0 ;
}
整合为工具类:
package com.yanqun.util;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.io.InputStream;
import java.util.Properties;
public class DataSourceUtil {
//获取dbcp方式的ds对象
public static DataSource getDataSourceWIthDBCP(){
BasicDataSource dbcp = new BasicDataSource();
dbcp.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dbcp.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
dbcp.setUsername("scott");
dbcp.setPassword("tiger");
dbcp.setInitialSize(20);
dbcp.setMaxActive(10);
return dbcp;
}
public static DataSource getDataSourceWIthDBCPByProperties() throws Exception{
DataSource dbcp = null ;
Properties props = new Properties();
InputStream input = new DBCPDemo().getClass().getClassLoader().getResourceAsStream("dbcpconfig.properties");
props.load( input );
//只需要记住以下一句
dbcp = BasicDataSourceFactory.createDataSource(props ) ;
return dbcp;
}
public static DataSource getDataSourceWithC3P0(){
ComboPooledDataSource c3p0 = new ComboPooledDataSource();
try {
c3p0.setDriverClass("oracle.jdbc.driver.OracleDriver");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
c3p0.setJdbcUrl("jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
c3p0.setUser("scott");
c3p0.setPassword("tiger");
return c3p0 ;
}
public static DataSource getDataSourceWithC3P0ByXml(){
ComboPooledDataSource c3p0 = new ComboPooledDataSource("yanqun");
return c3p0 ;
}
}