一、数据库连接池
出现缘由:数据库的连接对象创建工作,比较消耗性能。
工作原理:在内存中开辟一块空间(集合),并放置多个连接对象。需要连接的话,直接从内存空间中获取。不需要创建连接对象。使用完毕,归还连接对象。确保连接对象能循环利用。
二、自定义数据库连接池
通过数据库连接池工作原理,自定义数据库连接池需要以下几步:
①、内存中开辟空间
②、创建数据库连接对象,并放置到内存中
③、定义获取数据库连接对象的方法
④、定义释放(归还)数据库连接对象的方法
代码实现:
/** * @Title: MyDataSource * @Description: sun公司提供数据库连接池规范是以DataSource命名的 * @author: marw * @date 2020/03/26 16:16:58 */ public class MyDataSource implements DataSource { //①、开辟空间 List<Connection> list=new ArrayList<Connection>(); /** * ②、创建数据库连接对象,并放置到内存中 */ public MyDataSource() { for (int i = 0; i < 10; i++) { Connection connection = JDBCUtil.getConnection(); list.add(connection); } } /** * ③、 sun公司 提供数据库连接池规范中包含了获取数据库连接对象的方法 * 只需要重写此方法 */ @Override public Connection getConnection() throws SQLException { //内存扩容 if (list.size() == 0) { for (int i = 0; i < 3; i++) { Connection connection = JDBCUtil.getConnection(); list.add(connection); } } // 移除集合中第一个元素(数据库连接对象),并获取移除的元素 return list.remove(0); } /** * ④、释放(归还)数据库连接对象 */ public void Liberate(Connection connection) { list.add(connection); } ... ... }
使用自定义数据库连接池
public class TestPool { @Test public void testPool() { Connection connection=null; PreparedStatement ps =null; MyDataSource dataSource=null; try { MyDataSource dataSource=new MyDataSource(); connection=dataSource.getConnection(); String sql="insert into account values(?,?)"; ps =connection.prepareStatement(sql); ps.setString(1, "qian"); ps.setInt(2, 1000); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally {
dataSource.Liberate(connection);//释放连接对象 JDBCUtil.release(connection, ps); } } }
使用自定义数据库连接池,有以下几个问题
①、每次使用都需要自己创建新的连接池对象,那样的话每一次访问都会创建10连接池对象,这个需要使用单例解决
②、无法面向接口编程,Liberate方法,不想自定义方法可以重写Connection接口的close方法,让它实现归还连接对象。
想要扩展Connection接口的close方法
Ⅰ、直接修改方法
Ⅱ、继承,必须知道Connection接口的实现类
Ⅲ、装饰模式
使用装饰模式代码:
public class ConnectionWrap implements Connection { Connection connection=null; List<Connection> list=null; public ConnectionWrap(Connection connection,List<Connection> list) { super(); this.connection=connection; this.list=list; } @Override public void close() throws SQLException { list.add(connection); } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return connection.prepareStatement(sql); } ... ... }
使用装饰模式对象
public class MyDataSource implements DataSource { //①、开辟空间 List<Connection> list=new ArrayList<Connection>(); /* 单例 start */ private static MyDataSource dataSource=new MyDataSource(); /** * ②、创建数据库连接对象,并放置到内存中 */ private MyDataSource() { for (int i = 0; i < 10; i++) { Connection connection = JDBCUtil.getConnection(); list.add(connection); } } public static MyDataSource getInstance() { return dataSource; } /* 单例 end */ /** * ③、 sun公司 提供数据库连接池规范中包含了获取数据库连接对象的方法 * 只需要重写此方法 */ @Override public Connection getConnection() throws SQLException { //内存扩容 if (list.size() == 0) { for (int i = 0; i < 3; i++) { Connection connection = JDBCUtil.getConnection(); list.add(connection); } } // 移除集合中第一个元素(数据库连接对象),并获取移除的元素 Connection conn=list.remove(0); // 装饰模式 返回Connection对象,进行装饰,使其对象的close方法,有归还功能 Connection connection = new ConnectionWrap(conn, list); return connection; } ... ... }
测试代码
public class TestPool { @Test public void testPool() { Connection connection=null; PreparedStatement ps =null; try { DataSource dataSource=MyDataSource.getInstance(); connection=dataSource.getConnection(); String sql="insert into account values(?,?)"; ps =connection.prepareStatement(sql); ps.setString(1, "qian"); ps.setInt(2, 1000); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtil.release(connection, ps); } } }
三、开源连接池
原文:https://www.cnblogs.com/WarBlog/p/12575896.html