通常在做java-web开发时,最需要做的就是配置数据库连接;从简单的jdbc直接使用到使用第三方分装的orm。在使用传统的jdbc进行数据库操作时,经常是当要进行一个数据库操作时,就开启一个数据库连接,操作完成后就关闭数据库连接。频繁的数据库连接对象的申请与释放,导致大量的资源耗费在了数据库连接创建与释放上面,而第三方的orm框架则采用了数据库连接池的办法,极大的优化了数据库连接的频繁申请与释放操作:需要进行数据库操作时,从数据库连接池中获取一个可用连接;不用时将连接返还给连接池;而连接池维护着每一个数据库连接的连接生命周期,只要还在数据库连接还在生命周期内,那么这个数据库连接就不会断开。
java数据库连接池的图示展示

java数据库连接池的实现思路
java数据库连接池在jdk中已经有相关的接口了——java.sql.DataSource;但是如果我们要手动实现一个数据库连接池的时候,应该怎么去做?数据库连接池最重要的是实现池的作用——成为数据库连接对象的容器以及管理容器内的所有数据库连接对象;实现当数据库连接断开时,连接对象不是被直接回收,而是重新回到容器中(这是最难的点);容器的话,可以采用线程安全的java.util.Vector来充当。而对象的重新回收到容器当中,可以利用java的代理机制来实现——实现数据库连接对象的代理。
java数据库连接池代码实现
1 2 3 4 5
| jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.0:3306/jdbcpool jdbc.username=root jdbc.password=xxxx jdbc.poolsize=10
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| import javax.sql.DataSource; 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.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.Vector; import java.util.logging.Logger;
public class MyDataSource implements DataSource {
private static Vector<Connection> connections = new Vector<>();
static { InputStream in = MyDataSource.class.getClassLoader().getResourceAsStream("myDB.properties"); Properties properties = new Properties(); try { properties.load(in); String driver = properties.getProperty("jdbc.driver"); String url = properties.getProperty("jdbc.url"); String username = properties.getProperty("jdbc.username"); String password = properties.getProperty("jdbc.password"); int poolsize = Integer.valueOf(properties.getProperty("jdbc.poolsize")); Class.forName(driver); for (int i = 0; i < poolsize; i ++) { Connection connection = DriverManager.getConnection(url, username, password); System.out.println("success get connection"); connections.addElement(connection); } } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
@Override public Connection getConnection() throws SQLException { if (connections.size()>0) { final Connection conn = connections.remove(0); System.out.println("jdbc pool size is :" + connections.size()); return (Connection) Proxy.newProxyInstance(MyDataSource.class.getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(!method.getName().equals("close")){ return method.invoke(conn, args); }else{ connections.addElement(conn); System.out.println(conn + "return to jdbc pool"); System.out.println("jdbc pool size is" + connections.size()); return null; } } }); }else { throw new RuntimeException("busy"); } }
@Override public Connection getConnection(String username, String password) throws SQLException { return null; }
@Override public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
@Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
@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; } }
|
数据库连接池测试(picture)

数据库连接池测试(Video)
bilibili video by Mynameis蠢逼