一、连接池
1.为什么要用连接池
与数据库的每个连接的建立和关闭,均会在数据库服务器端造成非常大的资源开销。
作为传统的数据库访问方式是:
一次数据库访问对应一个物理连接,每次操作数据库都需要打开、关闭该物理连接,系统性能损耗非常严重。
连接对象代表着数据库系统的连接进程,是有限的资源。如果系统的使用用户非常多,有可能超出数据库服务器的承受极限,造成系统的崩溃。
数据库连接池技术就是为了解决这一问题的方案:
当应用程序开始运行的时候,主动的与数据库获取足够的连接,组成一个池。每次应用程序请求数据库连接时,不用再重新从数据库连接,而是从池中取出已有的连接对象,使用完后,也不再关闭连接,而是归还连接到连接池中。
2.连接池管理连接原理:
1).当应用启动时,创建初始化数目的连接
2).为用户请求提供可用连接。当申请时无连接可用或者达到指定的最小连接数,按增量参数值创建新的连接
为确保连接池中最小的连接数的策略:
a.动态检查:定时检查连接池,一旦发现数量小于最小连接数,则补充相应的新连接,保证连接池正常运转
b.静态检查:空闲连接不足时,系统才检测是否达到最小连接数
3).将用户不再使用的连接标识为可用连接,等待其他用户请求。
4). 当空闲的连接数过多时,释放连接对象。
连接池也只是JDBC中定义的接口,具体实现由数据库厂商实现。常用的连接池实现组件有DBCP、c3p0和Druid等。
3.使用DBCP连接池
DBCP(DataBase connection pool):数据库连接池,是Apache的一个 Java 连接池开源项目,同时也是 Tomcat服务器使用的连接池组件。相当于是Apache开发的针对连接池接口的一个实现方案。
连接池是创建和管理连接的缓冲池技术,将连接准备好被任何需要它们的应用使用。
使用Apache DBCP需要三个实现jar包文件:
commons-dbcp2-2.5.0.jar 连接池的实现
commons-logging-1.2.jar 连接池实现的依赖库
commons-pool2-2.6.0.jar 连接池实现的依赖库
5.DataSource获取连接
先通过属性文件获取连接池参数,然后加载这些参数,获得连接:
//创建数据源对象
private static BasicDataSource dataSource = new BasicDataSource();
//加载参数,给数据源对象的属性赋值
dataSource.setDriverClassName(driveClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
//获得连接
Connection conn = dataSource.getConnection();
6.连接池参数设置
连接池常用参数有:
初始连接数
最大连接数
最小连接数
每次增加的连接数
超时时间
最大空闲连接
最小空闲连接
根据应用需要,设置合适的值。连接池本身设置有默认值,如果不设置,则使用默认值。
7.案例:使用Apache DBCP连接池重构DbUtil
要求:使用Apache DBCP连接池重构类DbUtil为DbUtil_Pool类,并重构案例“实现DbUtil_Pool,提供连接的获取,关闭功能”中的EmpDao类,在该类中使用DbUtil_Pool类来获取连接。
步骤一:导入使用DBCP组件所需的jar包
在JDBCDemo1工程下,导入使用DBCP组件所需的jar包,包括
commons-dbcp.jar以及commons-pool.jar两个jar包,这两个
jar包的名字可能会因为版本的不同,名字的最后为版本信息,
例如:commons-dbcp2-2.5.0.jar。
步骤二:重构db.properties文件
重构db.properties文件,在该文件中添加创建数据库连接
池所需的信息,包括初始化连接数、最大空闲连接数、
大小空闲连接数、最大连接数量以及超时回收时间。
项目结构
源码
package cn.lyc.util;
import java.io.IOException;
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 org.apache.commons.dbcp2.BasicDataSource;
public class DBUtils {
private static String DRIVER;//驱动连接
private static String URL;//数据库连接
private static String USER;//数据库用户
private static String PASSWORD;//数据用户密码
private static Properties props = new Properties();//配置文件对象
private static BasicDataSource dataSource = new BasicDataSource();//数据源
//连接池
private static int initSize;//初始连接数
private static int minIdle;//最小空闲数
private static int maxIdle;//最大空闲数据
private static int maxTotal;//最大连接数
private static long maxWait;//连接超时时间
static {
InputStream is = DBUtils.class.getClassLoader().getResourceAsStream("db.properties");//获取文件对象
try {
props.load(is);
DRIVER = props.getProperty("driver");
URL = props.getProperty("url");
USER = props.getProperty("user");
PASSWORD = props.getProperty("password");
initSize = Integer.valueOf(props.getProperty("initSize"));
minIdle = Integer.valueOf(props.getProperty("minIdle"));
maxIdle = Integer.valueOf(props.getProperty("maxIdle"));
maxTotal = Integer.valueOf(props.getProperty("maxTotal"));
maxWait = Long.valueOf(props.getProperty("maxWait"));
dataSource.setDriverClassName(DRIVER);
dataSource.setUrl(URL);
dataSource.setUsername(USER);
dataSource.setPassword(PASSWORD);
dataSource.setInitialSize(initSize);
dataSource.setMinIdle(minIdle);
dataSource.setMaxIdle(maxIdle);
dataSource.setMaxTotal(maxTotal);
dataSource.setMaxWaitMillis(maxWait);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 连接对象
* @return
*/
public static Connection getConnection(){
Connection connection =null;
try {
connection = dataSource.getConnection();
return connection;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 关闭资源
* @param cn 连接数据库对象
* @param st 操作sql语句对象
* @param rs 结果集
*/
public static void close(Connection cn , Statement st, ResultSet rs){
try {
if(!cn.isClosed()&& cn!=null){
cn.close();
}
if(!st.isClosed()&& st!=null){
st.close();
}
if(!rs.isClosed()&& rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 测试连接
* @param args
*/
public static void main(String[] args) {
System.out.println(getConnection());
}
}
db.properties
##连接四要素
driver=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
user=system
password=123456
##连接池参数配置
##初始连接数
initSize=4
##最小空闲连接
minIdle=4
##最大空闲连接
maxIdle=5
##最大连接数
maxTotal=8
##超时等待时间
maxWait=10000
测试效果:
package cn.lyc.dao;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import cn.lyc.entity.Emp;
import cn.lyc.util.DBUtils;
public class EmpDao {
public List<Emp> selectAll(){
List<Emp> emps = new ArrayList<Emp>();
Connection cn = null;
Statement st = null;
ResultSet rs = null;
cn = DBUtils.getConnection();
try {
st = cn.createStatement();
rs = st.executeQuery("select * from emp");
while(rs.next()){
Emp emp = new Emp();
emp.setEmp_no(rs.getInt(1));
emp.setEmp_name(rs.getString(2));
emp.setEmp_hiredate(rs.getDate(3));
emp.setSal(rs.getDouble(4));
emps.add(emp);
}
} catch (SQLException e) {
e.printStackTrace();
}
return emps;
}
public static void main(String[] args) {
EmpDao emp = new EmpDao();
List<Emp> ls = emp.selectAll();
System.out.println(ls);
}
}
结果: