1. 程式人生 > >java數據庫連接池技術簡單使用

java數據庫連接池技術簡單使用

util mysql 一個 dsta getc lean 創建 gin eat

JDBCDemo.java:
package com.itheima.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.itheima.pool.MyPool;

public class JDBCDemo {

	public static void main(String[] args) {
		
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		MyPool pool = new MyPool();
		try {
			conn = pool.getConnection();
			ps = conn.prepareStatement("select * from account");
			rs = ps.executeQuery();
			while(rs.next()) {
				String name = rs.getString(2);
				String salary = rs.getString(3);
				System.out.println(name + " : " + salary);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			//關閉數據庫連接
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					rs = null;
				}
			}
			if(ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					ps = null;
				}
			}
			/*
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					rs = null;
				}
			}
			*/
			//這裏不能關閉數據庫連接對象connection,應該將其返還給數據庫連接池
			pool.returnConn(conn);
		}
	}
}

MyPool.java:

package com.itheima.pool;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;

import javax.sql.DataSource;

public class MyPool implements DataSource{

	//list集合保存數據庫連接池中的connection對象
	private static List<Connection> pool = new LinkedList<Connection>();
	//靜態代碼塊。用於初始化list集合。即初始化數據庫連接池,創建5個connection對象保存當中以備使用
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			for(int i = 0; i < 5; i++) {
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
				pool.add(conn);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return null;
	}
	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
	}
	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
	}
	@Override
	public int getLoginTimeout() throws SQLException {
		return 0;
	}
	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		return null;
	}
	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	//重寫父類的getConnection()方法,返回數據庫連接池中的一個connection對象。
	//假設數據庫連接池中connection對象都已被使用。即都被取走未返還,則創建3個connection對象保存當中供以後使用
	@Override
	public Connection getConnection() throws SQLException {
		if(pool == null) {
			for(int i = 0; i < 3; i++) {
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
				pool.add(conn);
			}
		}
		return pool.remove(0);
	}
	//創建新方法。用於返回數據庫連接對象connection。由於dao層用完數據庫的連接後,不應該將其銷毀,而是應該將其返還給數據庫連接池
	public void returnConn(Connection conn) {
		pool.add(conn);
	}
	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	
}

以上代碼是數據庫連接池的簡單使用,可是有一個問題就是當你使用數據庫連接池技術時,你須要改動JDBCDemo.java文件裏finally代碼塊中的代碼,即conn對象在finally代碼塊裏不應該通過conn.close();方法關閉,而是應該返還給數據庫連接池。

這裏我們採用“動態代理”的方式,解決該問題,即finally代碼塊裏依舊調用conn.close();方法。

此時以上兩個java文件的代碼更改例如以下:

package com.itheima.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.itheima.pool.MyPool;

public class JDBCDemo {

	public static void main(String[] args) {
		
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		MyPool pool = new MyPool();
		try {
			conn = pool.getConnection();
			ps = conn.prepareStatement("select * from account");
			rs = ps.executeQuery();
			while(rs.next()) {
				String name = rs.getString(2);
				String salary = rs.getString(3);
				System.out.println(name + " : " + salary);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			//關閉數據庫連接
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					rs = null;
				}
			}
			if(ps != null) {
				try {
					ps.close();
				} catch (SQLException e) {
					ps = null;
				}
			}
			if(conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					conn = null;
				}
			}
		}
	}
}
package com.itheima.pool;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;

import javax.sql.DataSource;

public class MyPool implements DataSource{

	//list集合保存數據庫連接池中的connection對象
	private static List<Connection> pool = new LinkedList<Connection>();
	//靜態代碼塊,用於初始化list集合,即初始化數據庫連接池,創建5個connection對象保存當中以備使用
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			for(int i = 0; i < 5; i++) {
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
				pool.add(conn);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return null;
	}
	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
	}
	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
	}
	@Override
	public int getLoginTimeout() throws SQLException {
		return 0;
	}
	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		return null;
	}
	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	//重寫父類的getConnection()方法。返回數據庫連接池中的一個connection對象,
	//假設數據庫連接池中connection對象都已被使用。即都被取走未返還,則創建3個connection對象保存當中供以後使用
	@Override
	public Connection getConnection() throws SQLException {
		if(pool == null) {
			for(int i = 0; i < 3; i++) {
				Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
				pool.add(conn);
			}
		}
		final Connection conn = pool.remove(0);
		
		//使用動態代理改造close方法
		//newProxyInstance(類載入器, 要改造的conn對象所實現的全部接口,  匿名內部類)
		Connection proxy = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				if("close".equals(method.getName())) {
					//假設是close方法。我們進行重寫
					returnConn(conn);
					return null;
				} else {
					//假設是其它方法,直接調用
					return method.invoke(conn, args);
				}
			}
		});
		System.out.println("獲取一個連接對象,剩余連接對象:" + pool.size());
		return proxy;
	}
	//創建新方法,用於返回數據庫連接對象connection,由於dao層用完數據庫的連接後,不應該將其銷毀,而是應該將其返還給數據庫連接池
	public void returnConn(Connection conn) {
		pool.add(conn);
		System.out.println("返還一個連接對象,剩余連接對象:" + pool.size());
	}
	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	
}

執行結果:

獲取一個連接對象,剩余連接對象:4
a : 1000.0
b : 1000.0
c : 1000.0
返還一個連接對象,剩余連接對象:5


java數據庫連接池技術簡單使用