在大型项目中多次连接和释放数据库会造成资源浪费,使用连接池以节省资源。共享连接Connection,解决性能问题。实现javax.sql.DataSource连接池公共接口,常用的又DBCP,C3PO。
编写自定义连接池。MyDataSource类是自定义连接池类。
1、创建连接池,实现接口 2、提供集合 存放连接,因为需要经常添加和移除,选择LinkedList 3、需要连接时从集合中获取 4、使用完后归还
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;
import javax.sql.DataSource;
//自定义连接池代码实现
public class MyDataSource implements DataSource{//实现DataSource接口
//1:创建容器储存Connection对象
private static LinkedList<Connection> pool = new LinkedList<Connection>();
//2:创建连接
static{
for(int i=0;i<5;i++)
{
Connection conn = JdbcUtils.getConn();
pool.add(conn);
}
}
//重写获取连接的方法
@Override
public Connection getConnection() throws SQLException {
//3:使用前先判断池中还有没有链接
if(pool.size()==0)
{
for(int i=0;i<5;i++)
{
Connection conn = JdbcUtils.getConn();
pool.add(conn);
}
}
//4:从池中获取连接对象
return pool.remove(0);
}
//归还连接对象到连接池的方法
public void back(Connection conn){
pool.add(conn);
}
//更多实现方法没有给出
}
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
/*
* JdbcUtils类,获取连接和释放资源的工具类 与之前相同没有改变
*
* MyDataSource类,自定义连接池类 ,必须实现DataSource连接池公共接口,用工具类新建获取5个连接存入一个集合中
*
* Test1 检测是否能正常使用的方法类 再获取连接时新建一个连接池对象并再连接池中获取连接 而不是直接从工具类中获取连接
*
*观察最后finally中的方法,此时需要调用的是连接池对象的back方法释放资源。
* 我们希望调用close的时候也进行归还,此时便需要对close方法进行增强。
*/
public class Test1 {
@Test
public void test123(){
ResultSet rs = null;
PreparedStatement pstmt = null;
Connection conn =null;
MyDataSource my = new MyDataSource();//创建连接池对象
try {
//从连接池获取连接
conn=my.getConnection();
//查询
String sql = "select * from product where cid = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "1");
rs = pstmt.executeQuery();
while(rs.next())
{
System.out.println("pid:"+rs.getObject(1)+" name:"+rs.getObject(2)+" cid:"+rs.getObject(5));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
my.back(conn);
}
}
}
1、编写类MyConnection 实现Connection接口,在其中修改close方法使得是归还而不是关闭,并且完善其他需要调用的方法。
2、在连接池类MyDataSource 中添加连接时添加上面编写的修改后的类。
3、在Test 的时候finally 中直接调用close方法 完整代码如下。
1 JdbcUtils类 与之前没有改变
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ResourceBundle;
public class JdbcUtils {
private static String dirver;
private static String url;
private static String user;
private static String password;
static{
ResourceBundle bundle = ResourceBundle.getBundle("db");//不用后缀名
dirver = bundle.getString("jdbc.driver"); //获取配置文件中的字符串
url = bundle.getString("jdbc.url");
user = bundle.getString("jdbc.user");
password = bundle.getString("jdbc.password");
}
public static Connection getConn()
{
Connection conn =null;
try {
Class.forName(dirver);
conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
public static void release(ResultSet rs,PreparedStatement pstmt,Connection conn)
{
try {
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2、MyConnection类 实现连接接口 代码省略了部分没有用上的方法
//装饰者设计模式
//1:实现要增强的类 Connection
public class MyConnection implements Connection{
//定义变量
private Connection conn;
private LinkedList<Connection> pool;
//2:编写构造方法,存入
public MyConnection(Connection conn,LinkedList<Connection> pool){
this.conn=conn;
this.pool=pool;
}
//3:编写需要增强的方法
@Override
public void close() throws SQLException {
//现在 如果调用此方法 需要将conn归还连接池中。
//所以本类还需要连接池对象,让构造方法读入
pool.add(conn);
}
@Override
public PreparedStatement prepareStatement(String arg0) throws SQLException {
return conn.prepareStatement(arg0); //调用方法
}
@Override
public Statement createStatement() throws SQLException {
return conn.createStatement();
}
//省略更多没有用上的方法
}
3、MyDataSource 连接池类 省略了部分没有用上的方法
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;
import javax.sql.DataSource;
//自定义连接池代码实现
public class MyDataSource implements DataSource{
private static LinkedList<Connection> pool = new LinkedList<Connection>();
static{
for(int i=0;i<5;i++)
{
//添加的时候,添加的是增强的类 已经经过改造
Connection conn = JdbcUtils.getConn();
MyConnection myconn = new MyConnection(conn,pool);
pool.add(myconn);
}
}
@Override
public Connection getConnection() throws SQLException {
if(pool.size()==0)
{
for(int i=0;i<5;i++)
{
//添加增强类
Connection conn = JdbcUtils.getConn();
MyConnection myconn = new MyConnection(conn,pool);
pool.add(myconn);
}
}
//获取的也是已经增强过的对象
return pool.remove(0);
}
}
4、Test 检测
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
/*希望调用close时候也进行归还而不是关闭连接。使用装饰者设计模式,增强close方法
*
* JdbcUtils类 工具类
*
* MyDataSource类 往连接池里面添加连接的时候添加的是增强过的类对象
*
* MyConnection类 , 实现Connection接口,重写close方法以及创建sql执行者的方法
* 此时调用close方法将进行归还而不是关闭
*
* Test1 检测 尝试插入
*
*/
public class Test1 {
@Test
public void test123(){
Statement st = null;
PreparedStatement pstmt = null;
Connection conn =null;
MyDataSource my = new MyDataSource();
try {
conn=my.getConnection();
st = conn.createStatement(); //调用了conn的方法 需要在实现类中重写方法
//添加:
int r = st.executeUpdate("insert into product values(null,'王123',200,null,3)");
System.out.println(r);
} catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.release(null, pstmt, conn); //区别:直接调用conn的close方法即可
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}