JDBC連接池

在使用JDBC時我們可以自己去創建一個工具類(JDBCUtils),每次來調用它的方法來獲取連接或者來釋放連接,具體該類的實現如下:

package 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 driver;
	private static String url;
	private static String username;
	private static String password;
	//靜態代碼塊
	
	static {
		//讀取配置文件
		ResourceBundle bundle=ResourceBundle.getBundle("db");
		//獲取文件中的數據
		driver=bundle.getString("driver");
		url=bundle.getString("url");
		username=bundle.getString("username");
		password=bundle.getString("password");
	}
	//獲取連接
	public static Connection getConnection() {
		Connection conn = null;
		try {
			Class.forName(driver);
			conn=DriverManager.getConnection(url, username, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
	
	//釋放資源
	public static  void  release(Connection  conn,PreparedStatement pstmt,ResultSet rs){
		if(rs!=null)
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		if(pstmt!=null)
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		if(conn!=null)
			try {
				rs.close();
			} catch (SQLException e){ 
				e.printStackTrace();
			}
	}
}

在這裏我們使用配置文件來存儲鏈接數據庫所需要的信息,配置文件名爲db.properties

這個類中有兩個方法,一是來獲取數據庫的連接,二是來釋放資源

但是,如果反覆的創建資源釋放資源,這會造成很大的浪費,所以,我們可以使用jdbc連接池來存放,在連接池中我們可以存放多個已經事先創建好的連接,每次使用時只需要取出來,使用完後再放回去,這樣做提高了效率。

package DataSource;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.logging.Logger;

import javax.sql.DataSource;

import JDBCUtils.JDBCUtils;

public class MyDataSource implements DataSource{
	//創建集合用來存儲conn
	private static ArrayList<Connection> pool=new ArrayList<>();
	
	//使用靜態代碼塊創建5個連接放到連接池中
	static {
		Connection conn=null;
		for(int i=0;i<5;i++) {
			conn=JDBCUtils.getConnection();
			pool.add(conn);
		}
	}
	
	//寫返回類
	@Override
	public Connection getConnection() throws SQLException {
		Connection conn=null;
		//判斷是否爲空
		if(pool==null) {
			for(int i=0;i<5;i++) {
				conn=JDBCUtils.getConnection();
				pool.add(conn);
			}
		}
		//刪除第一個
		conn=pool.remove(0);
		return conn;
	}
	
	//寫回收方法
	public void backConnection(Connection conn){
		pool.add(conn);
	}

    //!!!!.....此處省略了很多需要寫上的類

}

創建連接池的大概思路就是,我們先創建一個集合(池),然後通過靜態代碼塊創建多個(上段代碼創建了5個)連接,然後將他們全部放到集合中,如果每次要獲得連接,直接從集合中取出一個,使用完後再調用這個類中的返回方法將連接歸還

這是測試類:

public class TestMyDataSource {

	@Test
	public void Test() {
		Connection conn=null;
		PreparedStatement pstmt=null;
		MyDataSource datasource=new MyDataSource();
		
		try {
			//獲取連接
			conn=datasource.getConnection();
			String sql="insert into t_user values(null,?,?)";
			pstmt=conn.prepareStatement(sql);
			pstmt.setString(1,"aaa"); 
			pstmt.setString(2,"666");
			int x=pstmt.executeUpdate();
			if(x>0) {
				System.out.println("操作成功");
			}else {
				System.out.println("操作失敗");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			datasource.backConnection(conn);
		}
	}
}

通過測試,成功的將數據填入數據庫中。

 

這是一種使用連接池的方法,如果我們要在最後依然習慣性的調用JDBCUtils中的方法release方法,但是這樣就會釋放連接,我們想讓他中的close方法不是釋放而是歸還,那麼我們就需要重寫這個方法,首先創建一個Connection類

package DataSource;

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class MyConnection implements Connection{
	
	private Connection conn;
	private ArrayList<Connection> pool;
	
	public MyConnection(Connection conn,ArrayList<Connection> pool){
		this.conn=conn;
		this.pool=pool;
	}

	@Override
	public PreparedStatement prepareStatement(String sql) throws SQLException {
		return conn.prepareStatement(sql);
	}
	
	@Override
	public void close() throws SQLException {
		pool.add(conn);
	}
	//!!!、、、、、此處省略了許多必須存在的方法
}

這裏我們牀架一個類,實際這個類就是對conn連接的一個封裝,我們再寫一個創建連接池的類,和上一個差不多

package DataSource;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.logging.Logger;

import javax.sql.DataSource;

import JDBCUtils.JDBCUtils;

public class MyDataSource1 implements DataSource{
	//創建集合用來存儲conn
	private static ArrayList<Connection> pool=new ArrayList<>();
	
	//使用靜態代碼塊創建5個連接放到連接池中
	static {
		Connection conn=null;
		for(int i=0;i<5;i++) {
			conn=JDBCUtils.getConnection();
			MyConnection myconn=new MyConnection(conn, pool);
			pool.add(myconn);
		}
	}
	
	//寫返回類
	@Override
	public Connection getConnection() throws SQLException {
		Connection conn=null;
		//判斷是否爲空
		if(pool==null) {
			for(int i=0;i<5;i++) {
				conn=JDBCUtils.getConnection();
			    MyConnection myconn=new MyConnection(conn, pool);
			    pool.add(myconn);
			}
		}
		//刪除第一個
		conn=pool.remove(0);
		return conn;
	}

    //此處省略多個必須存在方法

}

實際我們可以看到我們現在通過這個方法所得到的conn連接實際不是Connection瞭解,而是他的子類MyConnection,是一個封裝對象,我們再得到它後,就對它進行使用

        @Test
		public void Test1() {
			Connection myconn=null;
			PreparedStatement pstmt=null;
			MyDataSource1 datasource1=new MyDataSource1();
			
			try {
				//獲取連接
				myconn=datasource1.getConnection();
				String sql="insert into t_user values(null,?,?)";
				pstmt=myconn.prepareStatement(sql);
				pstmt.setString(1,"wae1"); 
				pstmt.setString(2,"6661");
				int x=pstmt.executeUpdate();
				if(x>0) {
					System.out.println("操作成功");
				}else {
					System.out.println("操作失敗");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				JDBCUtils.release(myconn, pstmt, null);
			}
		}

通過測試,成功的添加了信息到數據庫中,起始在全部過程中,我們所操作的只是Connection的封裝類,並沒有操作實際的Connec,最後調用JDBCUtils中的release方法,它中有close方法,再調用MyConnection中的close將連接放回連接池中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章