使用数据库连接池的原因:
- 传统方式创建和销毁连接都需要消耗系统资源
- 传统方式创建和销毁连接都需要消耗时间
使用数据库连接池的目的:
- 为了复用连接,代替传统的频繁占用系统资源和耗费时间的方式
- 便于管理连接,可以规定最大的连接数(控制应用服务器对数据库的并发访问)
实现的基本思想:
在要使用连接对象之前先创建好规定数量(根据服务器内存的承载能力制定)的连接对象存到放连接池(实现池子的方式一般是用链表结构的集合来实现)中,当应用服务器需要连接对象的时候就从连接池中获取,用完该连接对象时归还连接对象到连接池中。当应用服务器需要连接对象而当前池子中没有连接对象可取时,就让其先等待,如果等待超时还没有回获取到连接对象,就新建一个连接对象给服务器让其使用,用完后销毁该创建的对象。
实现一个最基本的连接池:
public class PersonalConnectionPool {
/**
* 用户名
*/
private static String user;
/**
* 密码
*/
private static String password;
/**
* 连接数据库的URL
*/
private static String url;
/**
* 连接池
* 规定最大连接数为3
*/
private static LinkedList<Connection> pool;
/**
* 从属性文件中加载数据库驱动,初始化连接池
*/
static{
try {
Properties properties = new Properties();
pool = new LinkedList<Connection>();
Class.forName("com.mysql.jdbc.Driver");
ClassLoader classLoader = PersonalConnectionPool.class.getClassLoader();
InputStream iStream = classLoader.getResourceAsStream("mysqlCongfig.properties");
properties.load(iStream);
user = properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
//创建三个连接对象(包装类对象)放到池子中
for (int i = 0; i < 3; i++) {
Connection connection = DriverManager.getConnection(url, user, password);
Connection connectionWrapper = new ConnectionWapper(connection,pool);
pool.add(connectionWrapper);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @throws SQLException
* @method 向外提供连接对象
*/
public Connection getConnection() throws SQLException {
Connection connection;
if(pool.size()>0)
{
connection = pool.removeFirst();
}
else
{
//等待超时,返回一个新创建的对象
connection = DriverManager.getConnection(url, user, password);
}
System.out.println("当前池子中有 "+pool.size()+" 个对象");
return connection;
}
/**
* 归还连接对象
* 直接简化在包装类的close方法中
*/
}
池子中用了到了一个包装类,包装了通过DriverManager.getConnection获取到的Connection的实现类对象,该包装也实现了Connection接口,重写了案例中需要的方法。该类结构如下:
public class ConnectionWapper implements Connection {
/**
* Connection接口的实现类对象的引用
*/
private Connection connection;
/**
* 存放连接包装对象的池子的引用
*
*/
private LinkedList<Connection> pool;
/**
*
* @param connection 的实现类对象
*/
public ConnectionWapper(Connection connection, LinkedList<Connection> pool) {
super();
this.connection = connection;
this.pool = pool;
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
PreparedStatement prepareStatement = connection.prepareStatement(sql);
return prepareStatement;
}
@Override
public void close() throws SQLException {
pool.add(this);
System.out.println("当前池子中有 "+pool.size()+" 个对象");
}
@Override
...
}
基于统一,JAVA为数据库连接池提供了公共接口,要求所有项目开发的连接池必须实现DataSource接口,可一统一用一套接口的方法使用不同开发商的数据库连接池。
常用的连接池:
每种连接池都可以使用直接创建连接池对象或者通过工厂的方式创建连接池对象,都可以使用xxx.properties或者xxx.xml文件来配置连接池。
dbcp连接池
- 封装dbcp连接池创建一个数据库工具类
/**
* (封装dbcp连接池来创建数据库工具类)
* (属性文件为源文件夹properties下的dbcpconfig.properties)
*/
public class DatabaseUtil {
/**
* 数据库连接池(dbcp连接池)对象引用
*/
private static DataSource dbcpPoor;
/**
* 只执行一次
*/
static {
Properties properties = new Properties();
ClassLoader classLoader = DatabaseUtil.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("dbcpconfig.properties");
try {
properties.load(resourceAsStream);
//通过直接创建连接池对象并设置参数方法创建连接池对象
// BasicDataSource basicDataSource = new BasicDataSource();
// basicDataSource.setUsername(properties.getProperty("username"));
// basicDataSource.setPassword(properties.getProperty("password"));
// basicDataSource.setDriverClassName(properties.getProperty("driverClassName"));
// basicDataSource.setUrl(properties.getProperty("url"));
//
// dbcpPoor = basicDataSource;
//通过工厂的方法创建连接池对象
dbcpPoor = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 获取连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
Connection connection = dbcpPoor.getConnection();
System.out.println("获取连接对象成功");
return connection;
}
/**
* 关闭资源
*/
//关闭建立的连接对象,释放资源
public static void closeSourceConnection(Connection connection, Statement statement, ResultSet resultSet){
try {
if (connection!=null) {
connection.close();
}
if (statement!=null) {
statement.close();
}
if (resultSet!=null) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static DataSource getDbcpPoor() {
return dbcpPoor;
}
}
c3p0连接池
- 封装c3p0连接池创建一个数据库工具类
/**
* (封装c3p0连接池来创建数据库工具类)
* @author YanoHao
*
*/
public class DatabaseUtil {
/**
* c3p0连接池对象的引用
*/
private static DataSource c3p0Poor;
/**
* 创建一次
*/
static {
//直接创建连接池对象(自动加载配置文件,无需设置参数)
c3p0Poor = new ComboPooledDataSource();
//通过工厂的方式创建连接池对象
// try {
// DataSource unpooledDataSource = DataSources.unpooledDataSource();
// c3p0Poor = DataSources.pooledDataSource(unpooledDataSource);
// } catch (SQLException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
/**
* 获取连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
Connection connection = c3p0Poor.getConnection();
System.out.println("获取连接对象成功");
return connection;
}
/**
* 关闭资源
*/
//关闭建立的连接对象,释放资源
public static void closeSourceConnection(Connection connection, Statement statement, ResultSet resultSet){
try {
if (connection!=null) {
connection.close();
}
if (statement!=null) {
statement.close();
}
if (resultSet!=null) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static DataSource getC3p0Poor() {
return c3p0Poor;
}
}
druid连接池
- 封装druid连接池创建一个数据库工具类
/*
* 封装druid连接池创建工具类
*/
public class DatabaseUtil {
/**
* 数据库连接池(druid连接池)对象引用
*/
private static DataSource druidPool;
static {
try {
Properties properties = new Properties();
ClassLoader classLoader = DatabaseUtil.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("druidconfig.properties");
properties.load(resourceAsStream);
//通过直接创建连接池对象的方式创建连接池对象
// DruidDataSource druidDataSource = new DruidDataSource();
// druidDataSource.setUsername(properties.getProperty("username"));
// druidDataSource.setPassword(properties.getProperty("password"));
// druidDataSource.setUrl(properties.getProperty("url"));
// druidDataSource.setDriverClassName(properties.getProperty("driverClassName"));
// druidPool = druidDataSource;
//通过工厂的方式创建连接池对象
druidPool = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException{
Connection connection = druidPool.getConnection();
return connection;
}
/**
*
* 关闭建立的连接对象,释放资源
*/
public static void closeSourceConnection(Connection connection, Statement statement, ResultSet resultSet){
try {
if (connection!=null) {
connection.close();
}
if (statement!=null) {
statement.close();
}
if (resultSet!=null) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static DataSource getDruidPool() {
return druidPool;
}
}