万字详解数据库连接池

数据库连接池的概念

  • 数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。
  • 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。这项技术能明显提高对数据库操作的性能。

自定义连接池

  • java.sql.DataSource接口:数据源(数据库连接池)。java官方提供的数据库连接池规范(接口)
    • 获取数据库连接对象:Connection getConnection();

工具类:

package com.dataSource;import java.io.InputStream;
import java.sql.*;
import java.util.Properties;public class JDBCUtils {/*** 1.私有构造方法*/private JDBCUtils() {}// 2.声明配置信息变量private static String driverClass;private static String url;private static String username;private static String password;private static Connection con;// 3.静态代码块中实现加载配置文件和注册驱动static {try {// 通过类加载器返回配置文件的字节流// getClassLoader().getResourceAsStream:通过给定名称查找资源,查询资源的规则由给定的类的class load来实现,这个方法由类的loader来执行;如果这个类由bootstrap加载,那么方法由ClassLoader.getSystemResourceAsStream代理执行。InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");// 创建Properties集合,加载流对象的信息Properties prop = new Properties();prop.load(is);// 获取信息为变量赋值driverClass = prop.getProperty("driverClass");url = prop.getProperty("url");username = prop.getProperty("username");password = prop.getProperty("password");// 注册驱动Class.forName(driverClass);} catch (Exception e) {e.printStackTrace();}}//4.获取数据库连接的方法public static Connection getConnection() {try {con = DriverManager.getConnection(url, username, password);} catch (SQLException e) {e.printStackTrace();}return con;}//5.释放资源的方法public static void close(Connection con, Statement stat, ResultSet rs) {if (con != null) {try {con.close();} catch (SQLException e) {e.printStackTrace();}}if (stat != null) {try {stat.close();} catch (SQLException e) {e.printStackTrace();}}if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}}public static void close(Connection con, Statement stat) {close(con, stat, null);}
}

自定义连接池:

package com.dataSource;import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;public class MyDataSource implements DataSource {// 定义集合容器,用于保存多个数据库连接对象private static final List<Connection> POOP = Collections.synchronizedList(new ArrayList<>());// 静态代码块,生成10个数据库连接保存到集合中static {for (int i = 0; i < 10; i++) {Connection coon = JDBCUtils.getConnection();POOP.add(coon);}}@Overridepublic Connection getConnection() throws SQLException {if (POOP.size() > 0) {Connection remove = POOP.remove(0);return remove;} else {throw new RuntimeException("连接数量耗尽");}}/**定义getSize方法,获取连接池容器的大小*/public int getSize() {return POOP.size();}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}
}

测试类:

package com.dataSource;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class DataSourceTest {public static void main(String[] args) throws SQLException {// 创建连接池对象MyDataSource dataSource = new MyDataSource();System.out.println("使用之前连接池数量:" + dataSource.getSize());// 通过连接池对象获取连接对象Connection conn = dataSource.getConnection();// 查看DriverManager连接的实现类,发现是JDBC4ConnectionSystem.out.println(conn.getClass());// 查询学生表的全部信息String sql = "SELECT * FROM student";PreparedStatement ps = conn.prepareStatement(sql);// 执行sql语句,接收结果集ResultSet rs = ps.executeQuery();while (rs.next()) {System.out.println(rs.getInt("sid") + "\t" + rs.getString("name") + "\t" + rs.getInt("age") + "\t" + rs.getDate("birthday"));}// 释放资源conn.close();ps.close();rs.close();System.out.println("使用之后连接池数量:" + dataSource.getSize());}
}

上面的代码是有问题的,因为最后释放了资源以后,通过查看使用后的连接池的数量发现没有归还操作,那连接池存在就没有意义了,连接池存在就是为了重复使用的。

连接池归还连接:

归还连接_继承:

通过打印连接对象,发现DriverManager获取的连接实现类是JDBC4Connection。

自定义一个类,继承JDBC4Connection这个类,定义连接对象和连接池容器对象的成员变量,通过有参构造对成员变量赋值,重写close()方法,将连接对象添加到池中
定义了子类完成了归还,但是DriverManager获取的还是JDBC4Connection这个对象,不是定义的子类,所以继承搞不了

归还连接_装饰设计模式:

自定义一个类,实现Connection接口,这样就和JDBC4Connection有相同的方法,重写close方法,剩余方法,只需要调用mysql驱动包的连接对象完成即可,但是这个设计模式需要重写很多的方法,比较麻烦

自定义类连接池:

package com.dataSource;import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;public class MyDataSource implements DataSource {// 定义集合容器,用于保存多个数据库连接对象private static final List<Connection> pool = Collections.synchronizedList(new ArrayList<>());// 静态代码块,生成10个数据库连接保存到集合中static {for (int i = 0; i < 10; i++) {Connection coon = JDBCUtils.getConnection();pool.add(coon);}}// 从连接池返回一个数据库连接@Overridepublic Connection getConnection() {if (pool.size() > 0) {// 从池中获取数据库连接Connection con = pool.remove(0);// 通过自定义连接对象进行包装MyConnection mycon = new MyConnection(con, pool);// 返回包装后的连接对象return mycon;} else {throw new RuntimeException("连接数量耗尽");}}/**定义getSize方法,获取连接池容器的大小*/public int getSize() {return pool.size();}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}
}

自定义连接类:

package com.dataSource;import java.sql.*;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;/*自定义Connection类。通过装饰设计模式,实现和mysql驱动包中的Connection实现类相同的功能!实现步骤:1.定义一个类,实现Connection接口2.定义Connection连接对象和连接池容器对象的变量3.提供有参构造方法,接收连接对象和连接池对象,对变量赋值4.在close()方法中,完成连接的归还5.剩余方法,还是只需要调用mysql驱动包的连接对象完成即可*/public class MyConnection implements Connection {private Connection con;private List<Connection> pool;public MyConnection(Connection con, List<Connection> pool) {this.con = con;this.pool = pool;}@Overridepublic void close() throws SQLException {pool.add(con);}@Overridepublic Statement createStatement() throws SQLException {return con.createStatement();}@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {return con.prepareStatement(sql);}@Overridepublic CallableStatement prepareCall(String sql) throws SQLException {return con.prepareCall(sql);}@Overridepublic String nativeSQL(String sql) throws SQLException {return con.nativeSQL(sql);}@Overridepublic void setAutoCommit(boolean autoCommit) throws SQLException {con.setAutoCommit(autoCommit);}@Overridepublic boolean getAutoCommit() throws SQLException {return con.getAutoCommit();}@Overridepublic void commit() throws SQLException {con.commit();}@Overridepublic void rollback() throws SQLException {con.rollback();}@Overridepublic boolean isClosed() throws SQLException {return con.isClosed();}@Overridepublic DatabaseMetaData getMetaData() throws SQLException {return con.getMetaData();}@Overridepublic void setReadOnly(boolean readOnly) throws SQLException {con.setReadOnly(readOnly);}@Overridepublic boolean isReadOnly() throws SQLException {return con.isReadOnly();}@Overridepublic void setCatalog(String catalog) throws SQLException {con.setCatalog(catalog);}@Overridepublic String getCatalog() throws SQLException {return con.getCatalog();}@Overridepublic void setTransactionIsolation(int level) throws SQLException {con.setTransactionIsolation(level);}@Overridepublic int getTransactionIsolation() throws SQLException {return con.getTransactionIsolation();}@Overridepublic SQLWarning getWarnings() throws SQLException {return con.getWarnings();}@Overridepublic void clearWarnings() throws SQLException {con.clearWarnings();}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {return con.createStatement(resultSetType,resultSetConcurrency);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return con.prepareStatement(sql,resultSetType,resultSetConcurrency);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return con.prepareCall(sql,resultSetType,resultSetConcurrency);}@Overridepublic Map<String, Class<?>> getTypeMap() throws SQLException {return con.getTypeMap();}@Overridepublic void setTypeMap(Map<String, Class<?>> map) throws SQLException {con.setTypeMap(map);}@Overridepublic void setHoldability(int holdability) throws SQLException {con.setHoldability(holdability);}@Overridepublic int getHoldability() throws SQLException {return con.getHoldability();}@Overridepublic Savepoint setSavepoint() throws SQLException {return con.setSavepoint();}@Overridepublic Savepoint setSavepoint(String name) throws SQLException {return con.setSavepoint(name);}@Overridepublic void rollback(Savepoint savepoint) throws SQLException {con.rollback(savepoint);}@Overridepublic void releaseSavepoint(Savepoint savepoint) throws SQLException {con.releaseSavepoint(savepoint);}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.createStatement(resultSetType,resultSetConcurrency,resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.prepareStatement(sql,resultSetType,resultSetConcurrency,resultSetHoldability);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.prepareCall(sql,resultSetType,resultSetConcurrency,resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {return con.prepareStatement(sql,autoGeneratedKeys);}@Overridepublic PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {return con.prepareStatement(sql,columnIndexes);}@Overridepublic PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {return con.prepareStatement(sql,columnNames);}@Overridepublic Clob createClob() throws SQLException {return con.createClob();}@Overridepublic Blob createBlob() throws SQLException {return con.createBlob();}@Overridepublic NClob createNClob() throws SQLException {return con.createNClob();}@Overridepublic SQLXML createSQLXML() throws SQLException {return con.createSQLXML();}@Overridepublic boolean isValid(int timeout) throws SQLException {return con.isValid(timeout);}@Overridepublic void setClientInfo(String name, String value) throws SQLClientInfoException {con.setClientInfo(name,value);}@Overridepublic void setClientInfo(Properties properties) throws SQLClientInfoException {con.setClientInfo(properties);}@Overridepublic String getClientInfo(String name) throws SQLException {return con.getClientInfo(name);}@Overridepublic Properties getClientInfo() throws SQLException {return con.getClientInfo();}@Overridepublic Array createArrayOf(String typeName, Object[] elements) throws SQLException {return con.createArrayOf(typeName,elements);}@Overridepublic Struct createStruct(String typeName, Object[] attributes) throws SQLException {return con.createStruct(typeName,attributes);}@Overridepublic void setSchema(String schema) throws SQLException {con.setSchema(schema);}@Overridepublic String getSchema() throws SQLException {return con.getSchema();}@Overridepublic void abort(Executor executor) throws SQLException {con.abort(executor);}@Overridepublic void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {con.setNetworkTimeout(executor,milliseconds);}@Overridepublic int getNetworkTimeout() throws SQLException {return con.getNetworkTimeout();}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return con.unwrap(iface);}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return con.isWrapperFor(iface);}
}
归还连接_适配器设计模式:

通过装饰设计模式有很多个需要实现的方法。这个时候就可以使用适配器设计模式了。提供一个适配器类,实现Connection接口,将所有功能进行实现(除了close方法)。自定义连接类只需要继承这个适配器类,重写需要改进的close()方法即可!

实现步骤:

  1. 定义一个适配器类,实现Connection接口
  2. 定义Connection连接对象的成员变量
  3. 通过有参构造方法完成对成员变量的赋值
  4. 重写所有方法(除close),调用mysql驱动包的连接对象完成
  5. 定义一个类,继承适配器父类
  6. 定义Connection连接对象和连接池容器对象的变量,通过有参构造进行赋值
  7. 重写close()方法中,完成归还连接
  8. 在自定义连接池中,将获取的连接对象通过自定义连接对象进行包装

适配器类:

package com.dataSource;import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;/* 定义一个适配器类,实现Connection接口定义Connection连接对象的成员变量通过有参构造方法完成对成员变量的赋值重写所有方法(除close),调用mysql驱动包的连接对象完成
*/public abstract class MyAdapter implements Connection {// 因为所有的方法还是要调用要有的连接对象所以需要有参把原有的对象接收进来// 一般适配器类都是抽象类,可以有抽象方法也可以有普通方法和构造private Connection con;public MyAdapter(Connection con) {this.con = con;}@Overridepublic Statement createStatement() throws SQLException {return con.createStatement();}@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {return con.prepareStatement(sql);}@Overridepublic CallableStatement prepareCall(String sql) throws SQLException {return con.prepareCall(sql);}@Overridepublic String nativeSQL(String sql) throws SQLException {return con.nativeSQL(sql);}@Overridepublic void setAutoCommit(boolean autoCommit) throws SQLException {con.setAutoCommit(autoCommit);}@Overridepublic boolean getAutoCommit() throws SQLException {return con.getAutoCommit();}@Overridepublic void commit() throws SQLException {con.commit();}@Overridepublic void rollback() throws SQLException {con.rollback();}@Overridepublic boolean isClosed() throws SQLException {return con.isClosed();}@Overridepublic DatabaseMetaData getMetaData() throws SQLException {return con.getMetaData();}@Overridepublic void setReadOnly(boolean readOnly) throws SQLException {con.setReadOnly(readOnly);}@Overridepublic boolean isReadOnly() throws SQLException {return con.isReadOnly();}@Overridepublic void setCatalog(String catalog) throws SQLException {con.setCatalog(catalog);}@Overridepublic String getCatalog() throws SQLException {return con.getCatalog();}@Overridepublic void setTransactionIsolation(int level) throws SQLException {con.setTransactionIsolation(level);}@Overridepublic int getTransactionIsolation() throws SQLException {return con.getTransactionIsolation();}@Overridepublic SQLWarning getWarnings() throws SQLException {return con.getWarnings();}@Overridepublic void clearWarnings() throws SQLException {con.clearWarnings();}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {return con.createStatement(resultSetType, resultSetConcurrency);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return con.prepareStatement(sql, resultSetType, resultSetConcurrency);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return con.prepareCall(sql, resultSetType, resultSetConcurrency);}@Overridepublic Map<String, Class<?>> getTypeMap() throws SQLException {return con.getTypeMap();}@Overridepublic void setTypeMap(Map<String, Class<?>> map) throws SQLException {con.setTypeMap(map);}@Overridepublic void setHoldability(int holdability) throws SQLException {con.setHoldability(holdability);}@Overridepublic int getHoldability() throws SQLException {return con.getHoldability();}@Overridepublic Savepoint setSavepoint() throws SQLException {return con.setSavepoint();}@Overridepublic Savepoint setSavepoint(String name) throws SQLException {return con.setSavepoint(name);}@Overridepublic void rollback(Savepoint savepoint) throws SQLException {con.rollback(savepoint);}@Overridepublic void releaseSavepoint(Savepoint savepoint) throws SQLException {con.releaseSavepoint(savepoint);}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {return con.prepareStatement(sql, autoGeneratedKeys);}@Overridepublic PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {return con.prepareStatement(sql, columnIndexes);}@Overridepublic PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {return con.prepareStatement(sql, columnNames);}@Overridepublic Clob createClob() throws SQLException {return con.createClob();}@Overridepublic Blob createBlob() throws SQLException {return con.createBlob();}@Overridepublic NClob createNClob() throws SQLException {return con.createNClob();}@Overridepublic SQLXML createSQLXML() throws SQLException {return con.createSQLXML();}@Overridepublic boolean isValid(int timeout) throws SQLException {return con.isValid(timeout);}@Overridepublic void setClientInfo(String name, String value) throws SQLClientInfoException {con.setClientInfo(name, value);}@Overridepublic void setClientInfo(Properties properties) throws SQLClientInfoException {con.setClientInfo(properties);}@Overridepublic String getClientInfo(String name) throws SQLException {return con.getClientInfo(name);}@Overridepublic Properties getClientInfo() throws SQLException {return con.getClientInfo();}@Overridepublic Array createArrayOf(String typeName, Object[] elements) throws SQLException {return con.createArrayOf(typeName, elements);}@Overridepublic Struct createStruct(String typeName, Object[] attributes) throws SQLException {return con.createStruct(typeName, attributes);}@Overridepublic void setSchema(String schema) throws SQLException {con.setSchema(schema);}@Overridepublic String getSchema() throws SQLException {return con.getSchema();}@Overridepublic void abort(Executor executor) throws SQLException {con.abort(executor);}@Overridepublic void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {con.setNetworkTimeout(executor, milliseconds);}@Overridepublic int getNetworkTimeout() throws SQLException {return con.getNetworkTimeout();}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return con.unwrap(iface);}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return con.isWrapperFor(iface);}
}

继承适配器类:

public class MyConnection2 extends MyAdapter {private Connection con;private List<Connection> pool;public MyConnection2(Connection con, List<Connection> pool) {super(con);this.con = con;this.pool = pool;}@Overridepublic void close() throws SQLException {pool.add(con);}
}

自定义连接池类:

public class MyDataSource implements DataSource {// 定义集合容器,用于保存多个数据库连接对象private static final List<Connection> pool = Collections.synchronizedList(new ArrayList<>());// 静态代码块,生成10个数据库连接保存到集合中static {for (int i = 0; i < 10; i++) {Connection coon = JDBCUtils.getConnection();pool.add(coon);}}// 从连接池返回一个数据库连接@Overridepublic Connection getConnection() {if (pool.size() > 0) {// 从池中获取数据库连接Connection con = pool.remove(0);// 通过自定义连接对象进行包装MyConnection mycon = new MyConnection(con, pool);// 返回包装后的连接对象return mycon;} else {throw new RuntimeException("连接数量耗尽");}}/**定义getSize方法,获取连接池容器的大小*/public int getSize() {return pool.size();}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}

测试类:

public class DataSourceTest {public static void main(String[] args) throws SQLException {// 创建连接池对象MyDataSource dataSource = new MyDataSource();System.out.println("使用之前连接池数量:" + dataSource.getSize());// 通过连接池对象获取连接对象Connection conn = dataSource.getConnection();// 查看DriverManager连接的实现类System.out.println(conn.getClass());// 查询学生表的全部信息String sql = "SELECT * FROM student";PreparedStatement ps = conn.prepareStatement(sql);// 执行sql语句,接收结果集ResultSet rs = ps.executeQuery();while (rs.next()) {System.out.println(rs.getInt("sid") + "\t" + rs.getString("name") + "\t" + rs.getInt("age") + "\t" + rs.getDate("birthday"));}// 释放资源conn.close();ps.close();rs.close();System.out.println("使用之后连接池数量:" + dataSource.getSize());}
}

适配器模式也可以实现,但是也很麻烦,说白了就是把装饰设计模式拆分了而已

连接池归还_动态代理:

经过适配器模式的改进,自定义连接类中的方法已经很简洁了。剩余所有的方法已经抽取到了适配器类中。但是适配器这个类还是我们自己编写的,也比较麻烦!所以可以使用动态代理的方式来改进。

自定义数据库连接池类:

public class MyDataSource implements DataSource{//定义集合容器,用于保存多个数据库连接对象private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>());//静态代码块,生成10个数据库连接保存到集合中static {for (int i = 0; i < 10; i++) {Connection con = JDBCUtils.getConnection();pool.add(con);}}//返回连接池的大小public int getSize() {return pool.size();}//动态代理方式@Overridepublic Connection getConnection() {if(pool.size() > 0) {//从池中获取数据库连接Connection con = pool.remove(0);Connection proxyCon = (Connection)Proxy.newProxyInstance(con.getClass().getClassLoader(), new Class[]{Connection.class}, new InvocationHandler() {/*执行Connection实现类所有方法都会经过invoke如果是close方法,则将连接还回池中如果不是,直接执行实现类的原有方法*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if(method.getName().equals("close")) {pool.add(con);return null;}else {return method.invoke(con,args);}}});return proxyCon;}else {throw new RuntimeException("连接数量已用尽");}}
}
C3P0:

C3P0是一个开源的JDBC连接池,简化了很多步骤

使用步骤:

  1. 导入jar包
  2. 导入配置文件到src目录下
  3. 创建c3p0连接池对象
  4. 获取数据库连接进行使用 注意:C3p0的配置文件会自动加载,但是必须叫c3p0-config.xmlc3p0-config.properties

在这里插入图片描述
C3p0测试类:

public class C3p0Test {public static void main(String[] args) throws Exception {// 这里是空参的话,加载的就是默认的C3p0,如果指定名称就可以用自定义的DataSource dataSource = new ComboPooledDataSource();// 通过连接池对象获取数据库连接Connection con = dataSource.getConnection();// 查询学生表的全部信息String sql = "SELECT * FROM student";PreparedStatement ps = con.prepareStatement(sql);// 执行sql语句,接收结果集ResultSet rs = ps.executeQuery();while (rs.next()) {System.out.println(rs.getInt("sid") + "\t" + rs.getString("name") + "\t" + rs.getInt("age") + "\t" + rs.getDate("birthday"));}// 释放资源con.close();ps.close();rs.close();}
}

测试连接池归还情况:

public class C3P0Test02 {public static void main(String[] args) throws Exception {DataSource dataSource = new ComboPooledDataSource();// 定的是10个连接池,如果是11=5个应该会在3秒以后去申请新的,然后报错for (int i = 0; i < 15; i++) {Connection con = dataSource.getConnection();System.out.println(i + "   " + con);// 执行到第六次的时候关闭,如果处理了close 地址值肯定是有两个重复的if (i == 6) {con.close();}}// 第6个的连接执行到的时候就关闭掉,可以看到打印结果第6、7次的地址值是一样的,有十一个地址值,说明是做了归还处理}
}

配置类:c3p0-config.xml

<c3p0-config><!-- 使用默认的配置读取连接池对象 --><default-config><!--  连接参数 --><property name="driverClass">com.mysql.cj.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost/db2</property><property name="user">root</property><property name="password">itzhuzhu</property><!-- 连接池参数 --><!--初始化的连接数量--><property name="initialPoolSize">5</property><!--最大连接数量  初始化为5,最大10,意思就是默认给5个,不够再要,但是最多10个--><property name="maxPoolSize">10</property><!--超时时间 毫秒--><property name="checkoutTimeout">3000</property></default-config><!--这里是和上面一样的配置,但是c3p0默认的是上面这个,也可以自己加name,不指定的时候默认使用上面的--><named-config name="otherc3p0"> <!--  连接参数 --><property name="driverClass">com.mysql.cj.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/db2</property><property name="user">root</property><property name="password">itzhuzhu</property><!-- 连接池参数 --><property name="initialPoolSize">5</property><property name="maxPoolSize">8</property><property name="checkoutTimeout">1000</property></named-config>
</c3p0-config>
Druid:

阿里开发的数据库连接池工具,不会自动加载配置文件,需要手动去读取,文件名称可以随意取,连接池也不会释放。

使用步骤:

  1. 导入jar包
  2. 编写配置文件,放在src目录下
  3. 通过Properties集合加载配置文件
  4. 通过Druid连接池工厂类获取数据库连接池对象
  5. 获取数据库连接,进行使用

工具类:

public class DataSourceUtils {//1.私有构造方法private DataSourceUtils() {}//2.定义DataSource数据源变量private static DataSource dataSource;//3.提供静态代码块,完成配置文件的加载和获取连接池对象static {try {//加载配置文件InputStream is = DataSourceUtils.class.getClassLoader().getResourceAsStream("druid.properties");Properties prop = new Properties();prop.load(is);//获取数据库连接池对象dataSource = DruidDataSourceFactory.createDataSource(prop);} catch (Exception e) {e.printStackTrace();}}//4.提供获取数据库连接的方法public static Connection getConnection() {Connection con = null;try {con = dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return con;}//5.提供获取数据库连接池的方法public static DataSource getDataSource() {return dataSource;}//6.提供释放资源的方法public static void close(Connection con, Statement stat, ResultSet rs) {if (con != null) {try {con.close();} catch (SQLException e) {e.printStackTrace();}}if (stat != null) {try {stat.close();} catch (SQLException e) {e.printStackTrace();}}if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}}public static void close(Connection con, Statement stat) {close(con, stat, null);}
}

配置文件:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost/db2
username=root
password=itzhuzhu#初始化连接数量
initialSize=5#最大连接数量
maxActive=10#超时时间
maxWait=3000

测试类:

public class DruidTest {public static void main(String[] args) throws Exception {Connection con = DataSourceUtils.getConnection();// 查询学生表的全部信息String sql = "SELECT * FROM student";PreparedStatement ps = con.prepareStatement(sql);// 执行sql语句,接收结果集ResultSet rs = ps.executeQuery();while (rs.next()) {System.out.println(rs.getInt("sid") + "\t" + rs.getString("name") + "\t" + rs.getInt("age") + "\t" + rs.getDate("birthday"));}// 释放资源DataSourceUtils.close(con, ps, rs);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572211.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

编译OSG的FreeType插件时注意的问题

使用自己编译的freetype.lib&#xff0c;在编译osgdb_freetype插件项目时&#xff0c;报错LINK错误&#xff0c;找不到png的一堆函数 最简单的方式是不要使用PNG编译freetype。记住不要犯贱。 转载于:https://www.cnblogs.com/coolbear/p/7205906.html

高动态范围红外图像压缩

BF&DRC 近期看了一篇高动态范围红外图像压缩的文章&#xff0c;《New technique for the visualization of high dynamic range infrared images》.这篇文章主要利用双边滤波器把宽动态红外图像切割为基本图像和细节图像&#xff0c;再分别对基本图像和细节图像进行处理。对…

Mybatis构建sql语法

构建sql&#xff1a; 之前通过注解开发时&#xff0c;相关 SQL 语句都是自己直接拼写的。一些关键字写起来比较麻烦、而且容易出错。MyBatis 给我们提供了 org.apache.ibatis.jdbc.SQL 功能类&#xff0c;专门用于构建 SQL 语句 常用方法&#xff1a; 查询功能的实现&#xf…

在cli命令行上显示当前数据库,以及查询表的行头信息

在$HIVE_HOME/conf/hive-site.xml文件下加入以下配置文件 <property><name>hive.cli.print.header</name><value>true</value><description>Whether to print the names of the columns in query output.</description> </proper…

SAS笔记(2) RETAIN语句

本文重点&#xff1a; 使用RETIAN,INPUT在每次循环执行时保留上一次PDV中的变量值。SUM语句和SET语句会自动RETAIN变量。1. RETAIN语句 1.1 Example 1 先来看看在DATA步不使用和使用RETAIN语句的差异 没有使用RETAIN: DATA WITHOUT_1;PUT "Before the INPUT statement: &…

Hive优化策略

hive优化目标 在有限的资源下&#xff0c;运行效率高。常见问题 数据倾斜、Map数设置、Reduce数设置等 hive运行 查看运行计划 explain [extended] hql 例子 explain select no,count(*) from testudf group by no; explain extended select no,count(*) from testudf group …

GPU性能实时监测的实用工具

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

JSON转换工具

JSON的处理&#xff1a; JSON(JavaScript Object Notation)&#xff1a;是一种轻量级的数据交换格式。 它是基于 ECMAScript 规范的一个子集&#xff0c;采用完全独立于编程语言的文本格式来存储和表示数据。 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅…

Vue与Element入门使用

Vue&#xff1a; Vue是一套构建用户界面的渐进式前端框架。只关注视图层&#xff0c;并且非常容易学习&#xff0c;还可以很方便的与其它库或已有项目整合。通过尽可能简单的API来实现响应数据的绑定和组合的视图组件。视图&#xff1a;负责页面渲染&#xff0c;主要由HTMLCSS构…

Redis基础-下载安装配置

Nosql&#xff1a; NoSQL&#xff1a;即 Not-Only SQL&#xff08; 泛指非关系型的数据库&#xff09;&#xff0c;作为关系型数据库的补充。 作用&#xff1a; 应对基于海量用户和海量数据前提下的数据处理问题。 特征&#xff1a; 可扩容&#xff0c;可伸缩大数据量下高性能…

转:20分钟教你使用hexo搭建github博客

注册Github账号 这里我们就不多讲了&#xff0c;小伙伴们可以点击这里&#xff0c;进入官网进行注册。 创建仓库 图片来自Github登录账号后&#xff0c;在Github页面的右上方选择New repository进行仓库的创建。 图片来自Github在仓库名字输入框中输入&#xff1a; Github昵称.…

Maven入门详解与安装配置

Maven&#xff1a; Maven出现前的问题&#xff1a; 假设你现在做了一个项目&#xff0c;项目中肯定要用到一些jar包&#xff0c;比如说mybatis&#xff0c;log4j&#xff0c;JUnit等&#xff0c;除了这些之外&#xff0c;你有可能用到你的同事开发的其他的东西&#xff0c;比如…

Vue生命周期与自定义组件

自定义组件&#xff1a; Element 组件其实就是自定义的标签。例如<el-button> 就是对<button>的封装。 本质上&#xff0c;组件是带有一个名字且可复用的 Vue 实例&#xff0c;完全可以自己定义。 定义格式&#xff1a; Vue.component(组件名称, {props:组件的属性…

Spring DI(依赖注入)

DI依赖注入 IoC&#xff08;Inversion Of Control&#xff09;控制翻转&#xff0c;Spring反向控制应用程序所需要使用的外部资源DI&#xff08;Dependency Injection&#xff09;依赖注入&#xff0c;应用程序运行依赖的资源由Spring为其提供&#xff0c;资源进入应用程序的方…

Spring注解开发入门教程

注解开发&#xff1a; 什么是驱动注解&#xff1f; 注解启动时使用注解的形式替代xml配置&#xff0c;将繁杂的spring配置文件从工程中彻底消除掉&#xff0c;简化书写 注解驱动的弊端 为了达成注解驱动的目的&#xff0c;可能会将原先很简单的书写&#xff0c;变的更加复杂XM…

Spring整合Mybatis和JUnit

Spring整合Mybatis&#xff1a; 注解整合MyBatis分析 业务类使用注解形式声明bean&#xff0c;属性采用注解注入建立独立的配置管理类&#xff0c;分类管理外部资源&#xff0c;根据功能进行分类&#xff0c;并提供对应的方法获取bean使用注解形式启动bean扫描&#xff0c;加载…

Java-NIO(三):直接缓冲区与非直接缓冲区

直接缓冲区与非直接缓冲区的概念&#xff1a;1&#xff09;非直接缓冲区&#xff1a;通过 static ByteBuffer allocate(int capacity) 创建的缓冲区&#xff0c;在JVM中内存中创建&#xff0c;在每次调用基础操作系统的一个本机IO之前或者之后&#xff0c;虚拟机都会将缓冲区的…

Spring IOC扫描器与注册器

核心接口&#xff1a; 组件扫描器&#xff1a; 开发过程中&#xff0c;需要根据需求加载必要的bean&#xff0c;排除指定bean 设定组件扫描加载过滤器&#xff1a; 名称&#xff1a;ComponentScan 类型&#xff1a;类注解 位置&#xff1a;类定义上方 作用&#xff1a;设置…

Spring AOP切入点与通知XML类型

AOP&#xff1a; AOP(Aspect Oriented Programing)面向切面编程&#xff0c;一种编程范式&#xff0c;隶属于软工范畴&#xff0c;指导开发者如何组织程序结构AOP弥补了OOP的不足&#xff0c;基于OOP基础之上进行横向开发 uOOP规定程序开发以类为主体模型&#xff0c;一切围绕对…

给iOS项目中添加图片,并通过UIImageView引用和显示该UIImage图片

【问题】 关于iOS/iPhone中的文件选择对话框&#xff0c;用于用户去选择图片等文件 过程中&#xff0c;问题转换为&#xff0c;需要给当前iOS项目中&#xff0c;添加一个图片。 类似于Windows开发中的资源文件&#xff0c;其中图片文件属于资源的一种。 并且&#xff0c;接着可…