java數據庫連接池技術簡單使用
阿新 • • 發佈:2017-05-07
util mysql 一個 dsta getc lean 創建 gin eat
以上代碼是數據庫連接池的簡單使用,可是有一個問題就是當你使用數據庫連接池技術時,你須要改動JDBCDemo.java文件裏finally代碼塊中的代碼,即conn對象在finally代碼塊裏不應該通過conn.close();方法關閉,而是應該返還給數據庫連接池。
執行結果:
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數據庫連接池技術簡單使用