一、为什么会产生连接池?
我们现在考虑:
程序中连接为什么要来管理?因为连接资源宝贵,所以我们要来对连接资源进行管理
如何高效的来进行管理?频繁的连接,打开、关闭,这会严重影响程序的运行效率!所以我们引入连接池的概念。
二、何为连接池?
普通的连接:
- 操作数据库,创建连接。
- 操作结束,关闭!
使用连接池管理:
- 预先创建一组连接,有的时候每次取出一个。
- 用完后,放回。
连接池就好比图书馆,我们想要看书去借阅,看完之后我们要归还。就是借与还的关系。
三、学习连接池
3.1、自定义连接池
/* * * 自定义连接池, 管理连接 * 代码实现: 1. MyPool.java 连接池类, 2. 指定全局参数: 初始化数目、最大连接数、当前连接、 连接池集合 3. 构造函数:循环创建3个连接 4. 写一个创建连接的方法 5. 获取连接 ------> 判断: 池中有连接, 直接拿 ------> 池中没有连接, ------> 判断,是否达到最大连接数; 达到,抛出异常;没有达到最大连接数, 创建新的连接 6. 释放连接 -------> 连接放回集合中(..) */ private int init_count=3; //初始化连接数目 private int max_count=6; //最大连接数目 private int current_count=0; //记录当前使用连接数目 //连接池,存放所有的初始化连接 private LinkedList<Connection> pool=new LinkedList<Connection>(); //1.构造函数,初始化连接放入连接池 public MyPool(){ for(int i=0;i<init_count;i++){ //记录当前的数目 current_count++; //创建原始的连接对象,加入连接池 pool.addLast(createConnection()); } } //2. 创建一个新的连接的方法 //使用代理模式,来监测 close方法,当关闭时候,自动加入连接池 private Connection createConnection(){ try { Class.forName("com.mysql.jdbc.Driver"); final Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_demo", "root", "root"); Connection proxy=(Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), new Class[]{Connection.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Object result=null; String name=method.getName(); if("close".equals(name)){ if(pool.size()<init_count){ System.out.println("begin:当前执行close方法开始!"); // 连接放入连接池 (判断..) pool.addLast(conn); System.out.println("end: 当前连接已经放入连接池了!"); }else{ current_count--; conn.close(); } }else{ method.invoke(conn, args); } return result; } } ); return proxy; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } //获得连接 public Connection getConnection(){ if(pool.size()>0){ //连接池有,直接获取 return pool.removeFirst(); } if(current_count<max_count){ //连接池没有,小于最大连接,自己创建连接 current_count++; return createConnection(); } throw new RuntimeException();//没有连接使用,抛出异常 } //释放连接 public void realeaseConnection(Connection conn){ if(pool.size()<init_count){ pool.addLast(conn); }else{ current_count--; try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
为什么使用LinkedList集合?
因为LinkedList集合含有.removeFirst()方法,这样我们可以删除第一个元素,并且返回第一个元素
3.2开源的连接池技术
概述:
Sun公司约定: 如果是连接池技术,需要实现一个接口! javax.sql.DataSource;
3.2.1、DBCP连接池
核心类:BasicDataSource
// 1. 硬编码方式实现连接池 @Test public void testDbcp() throws Exception { BasicDataSource bds=new BasicDataSource(); //创建核心类 bds.setDriverClassName("com.mysql.jdbc.Driver"); //数据库驱动 bds.setUrl("jdbc:mysql://localhost:3306/jdbc_demo"); //数据库连接字符 bds.setUsername("root"); //数据库用户名 bds.setPassword("root");//数据库密码 bds.setInitialSize(3); //初始化连接 bds.setMaxActive(6);//最大连接数目 bds.setMaxIdle(3000);//最大休闲时间 String sql="select * from admin where id=5"; //获取连接 Connection conn=bds.getConnection(); PreparedStatement pstmt=conn.prepareStatement(sql); System.out.println(pstmt.execute()); conn.close(); } // 2. 【推荐】配置方式实现连接池 , 便于维护 @Test public void testDBCP() throws Exception { // 获取文件流 InputStream inputStream=App_DBCP.class.getResourceAsStream("/db.properties"); // 加载prop配置文件 Properties prop=new Properties(); prop.load(inputStream); // 根据prop配置,直接创建数据源对象 DataSource ds=BasicDataSourceFactory.createDataSource(prop); String sql="select * from admin where id=5"; //获取连接 Connection conn=ds.getConnection(); PreparedStatement pstmt=conn.prepareStatement(sql); System.out.println(pstmt.execute()); conn.close(); }
配置文件为db.properties,配置文件中的key与BaseDataSouce中的属性一样:
url=jdbc:mysql://localhost:3306/jdbc_demo driverClassName=com.mysql.jdbc.Driver username=root password=root initialSize=3 maxActive=6 maxIdle=3000
3.2.1、DBCP连接池
C3P0连接池:
最常用的连接池技术!Spring框架,默认支持C3P0连接池技术!
C3P0连接池,核心类:
CombopooledDataSource ds;
package cn.lyjs.c3p0; import static org.junit.Assert.*; import java.sql.Connection; import org.junit.Test; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0 { //1. 硬编码方式,使用C3P0连接池管理连接 @Test public void testCode() throws Exception { // 创建连接池核心工具类 ComboPooledDataSource dataSource=new ComboPooledDataSource(); // 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数 dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setUser("root"); dataSource.setPassword("root"); dataSource.setInitialPoolSize(3); dataSource.setMaxPoolSize(6); dataSource.setMaxIdleTime(3000); String sql="delete from admin where id=6"; Connection conn=dataSource.getConnection(); conn.prepareStatement(sql).executeUpdate(); conn.close(); } //2. XML配置方式,使用C3P0连接池管理连接 @Test public void testXml() throws Exception { // 创建c3p0连接池核心工具类 // 自动加载src下c3p0的配置文件【c3p0-config.xml】 ComboPooledDataSource dataSource=new ComboPooledDataSource(); String sql="delete from admin where id=7"; Connection conn=dataSource.getConnection(); conn.prepareStatement(sql).executeUpdate(); conn.close(); } }
c3p0-config.xml,配置文件
<c3p0-config> <default-config> <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="user">root</property> <property name="password">root</property> <property name="initialPoolSize">3</property> <property name="maxPoolSize">6</property> <property name="maxIdleTime">1000</property> </default-config> <named-config name="oracle_config"> <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="user">root</property> <property name="password">root</property> <property name="initialPoolSize">3</property> <property name="maxPoolSize">6</property> <property name="maxIdleTime">1000</property> </named-config> </c3p0-config>
时间: 2024-10-05 11:11:16