连接池的实现
基本思想:之前使用JDBC得到一个Connection是使用 DriverManager 获得一个Connection,随时用,随时创建Connection。而连接池则是通过重写 java.sql.DataSource 的方法得到Connection以及包装Connection的方法完成close操作。
具体步骤:通过创建 Mydatasource implements datascource 首先就在这里通过 LinkedList 创建好10个Connection ,重写getConnection返回LinkedList里的Connection ,在这里需要包装Connection的close()方法(使得用完了的connection返回到LinkedList里面去)
TestJDBC.java
package com.datasource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestJDBC {
public void test1() {
Connection conn = null;
PreparedStatement ps = null;
DataSource ds = new MyDataSource();
try {
conn = ds.getConnection();//从池中取出一个连接
ps = conn.prepareStatement("...");
}catch (SQLException e){
e.printStackTrace();
}finally {
try{
conn.close();//调用的是包装后的方法,使得用完的conn返回到连接池中
}
catch (SQLException e){
e.printStackTrace();
}
}
}
}
Mydatasource.java
package com.datasource;
import com.util.DButils;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.*;
import java.util.Collections;
import java.util.LinkedList;
import java.util.logging.Logger;
public class MyDataSource implements DataSource {
//创建一个存放连接的池子
private static LinkedList<Connection> pool = (LinkedList<Connection>) Collections.synchronizedList(new LinkedList<Connection>());
static{
try {
for (int i = 0; i < 10; i++) {
Connection conn = DButils.getConnection();
pool.add(conn);
}
}catch(SQLException e){
throw new ExceptionInInitializerError("初始化数据库连接失败,请检查配置文件是否正确");
}
}
public Connection getConnection() throws SQLException {
Connection conn = null;
if(pool.size()>0){
conn = pool.removeFirst();//从池中取出一个连接
Connection myConn = new MyConnection(conn,pool);//得到一个包装后的MyConnection对象
return myConn;
}else{
//等待
//新创建一个连接
throw new RuntimeException("服务器忙。。。");
}
}
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public ConnectionBuilder createConnectionBuilder() throws SQLException {
return null;
}
//...省略需要重写的方法
}
MyConnection.java
package com.datasource;
import java.sql.*;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
public class MyConnection implements Connection {
private Connection oldConnection;//com.mysql.jdbc.Connection
private LinkedList<Connection> pool;//连接池对象
public MyConnection(Connection oldConnection, LinkedList<Connection>pool){
this.oldConnection = oldConnection;//得到com.mysql.jdbc.Connection
this.pool = pool;//得到连接池对象
}
public void close() throws SQLException {
pool.addLast(oldConnection);
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
return oldConnection.prepareStatement(sql); //这些语句就依然调用原来的方法
}
@Override
public Statement createStatement() throws SQLException {
return oldConnection.createStatement();
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return oldConnection.prepareCall(sql);
}
@Override
public String nativeSQL(String sql) throws SQLException {
return oldConnection.nativeSQL(sql);
}
//假设所有需要重写的方法都写完了调用的原来自己的方法
}
有个很明显的缺点在于,其他不用的方法,需要全部自己实现调用原来的方法,那么解决这个问题,需要使用适配器
1)public class MyConnectionWraper implements Connection //这里面提前写好oldConn里面所有的调用原来的方法。
2)public class MyConnection extends MyConnectionWarper //这样这里只需要写你需要修改的方法,如close()