问题:
前面介绍了使用JDBC来获取数据库的连接,这种方法适用于适用于用户较少的时候,但当用户连接量较大时,资源消耗问题就凸显而出;当一个网站有20万个用户访问时,用户的每次请求都会向数据库获取连接,那么数据库服务器就要创建20万次连接,而数据库创建连接时会消耗较大的资源,创建的时间也相对较长,容易造成数据库服务器内存溢出、拓机等问题。因此对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。
解决办法:使用数据库连接池优化性能
数据库连接池(DataBase Connecyion Poll):
DBCP(DataBase Connection Pool)数据库连接池是 apache 上的一个Java连接池项目。DBPC负责分配、管理和释放数据库连接,建立的连接放在内存中(即连接池中),应用程序需要建立数据库连接时直接到从接池中申请一个连接使用,用完后由连接池回收该连接,从而达到连接复用,减少资源消耗的目的。
常见的数据库连接池:
DBPC数据库连接池
C3P0数据库连接池
使用DBPC:
这里我们先介绍DBPC数据库连接池。
要使用DBPC一是需要在应用程序中增加以下.jar包
commons-dbpc.jar 连接池的实现
commons-pool.jar 连接池实现的依赖库
二是在类目录下加入dbcp的配置文件:dbcpfactory.properties
dbcpfactory.properties的配置信息如下:
#连接设置
driverClassName=com.mysql.jdbc.Driver #驱动名
url=jdbc:mysql://localhost:3306/jdbcstudy #数据库url
username=root #数据库用户名
password=XDP #数据库密码
#<!-- 初始化连接 -->
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=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
创建初始化连接池(ConnectionPoll.class):
/**
* @author 北冥有熊
* 2018年11月24日
*/
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;
public class ConnectionPool {
/*
*在java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现
*DBCP连接池就是java.sql.DataSource接口的一个具体实现
*/
private static DataSource dSource = null;
//静态代码块中创建数据连接池
static {
try {
//加载dbcpfactory.properties配置文件
InputStream inputStream = ConnectionPool.class.getClassLoader().getResourceAsStream("dbcpfactory.properties");
//定义一个属性集,接收配置文件
Properties properties = new Properties();
properties.load(inputStream);
//传入属性集,生成DataSource对象
dSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return dSource.getConnection();
}
//关闭方法
public static void release(Connection conn,Statement stat,ResultSet rs) {
//关闭执行SQL命令的Statement对象
if(conn!=null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//将Connection连接对象交还给数据库连接池
if (stat!=null) {
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//关闭存储查询的ResultSet对象
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
测试DBPC
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* @author 北冥有熊
* 2018年11月24日
*/
public class DbcpTest {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement stat = null;
ResultSet rs = null;
try {
conn = ConnectionPool.getConnection();
String sql = "insert into stu(sname) values(?)";
stat = conn.prepareStatement(sql);
stat.setString(1, "55555");
stat.executeUpdate();
/*获取数据库自动生成主键 对于mysql-connector-java-5.1.7-bin.jar
* 不支持 getGeneratedKeys()这个方法,所以我们不能使用5.1.7的连接驱动来获取自动生成的主键,
* 在这里我们可以使用mysql-connector-java-5.0.8-bin.jar,换成这个jar文件之后,错误就没有了。
rs = stat.getGeneratedKeys();
if(rs.next()) {
System.out.println(rs.getInt(1));
}
*/
System.out.println("完毕");
} catch (Exception e) {
e.printStackTrace();
}finally {
ConnectionPool.release(conn, stat, rs);
}
}
}