本质:
不论是什么池,本质都是容器,用来存储对象
至于用什么容器存储就因人而异
至于存什么对象也因人而异
1.字符串常量池
2.数据库连接池
常见的数据库连接池有c3p0,druid等
这里演示c3p0
先在pom.xml中导入其依赖
<dependencies><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency></dependencies>
另外还需要导入mysql的驱动包,这里导入5.x版本,对应setDriverClass中的参数
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version></dependency>
不要忘了:导入包之后要点击刷新一下
不要忘了:导入包之后要点击刷新一下
不要忘了:导入包之后要点击刷新一下
public class C3P0test1 {public static void main(String[] args) throws PropertyVetoException, SQLException {//javax.sql包下的DataSource接口是所有第三方的数据源都要实现的接口,否则没法用java操作数据库ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setDriverClass("com.mysql.jdbc.Driver");dataSource.setUser("root");dataSource.setPassword("开机密码");dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/hanshangping");//下面两行设置数据库连接池中只有一个数据库连接对象,initial和max都得设置为1dataSource.setInitialPoolSize(1);dataSource.setMaxPoolSize(1);//java.sql包下的Connection接口//java.sql和javax.sql的区别//c3p0对java自带的DataSource和Connection都进行了实现Connection connection = dataSource.getConnection();System.out.println(connection);//com.mchange.v2.c3p0.impl.NewProxyConnection@52d455b8 [wrapping: com.mysql.jdbc.JDBC4Connection@4f4a7090]//c3p0的NewProxyConnection是一个代理类,也就是说该类中会存在mysql的数据库连接对象(代理类中一定要有被代理对象)Object inner = getInner(connection);System.out.println(inner.getClass().getName());//com.mysql.jdbc.JDBC4Connection,该类在导入的mysql-connector-java依赖中,数据库连接池出来之前我们一直使用的mysql连接类//数据库连接池就是对原生的mysql连接对象进行了代理,生成了代理连接对象}public static Object getInner(Object connection){Object result=null;Field field=null;try {field = connection.getClass().getDeclaredField("inner");//开启权限field.setAccessible(true);//获取传入的NewProxyConnection类中被代理的Connection对象result=field.get(connection);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}return result;}}
- 数据库连接池就是对驱动类中的连接对象进行代理,这也是驱动类的意义所在
- 我的理解是我们可以直接利用驱动类中的连接对象进行数据库连接,不过就不能有池化功能了
- 不论是驱动类还是数据库连接池,它们都得遵守java内部关于sql的接口规定

public class C3P0test1 {public static void main(String[] args) throws PropertyVetoException, SQLException {//javax.sql包下的DataSource接口是所有第三方的数据源都要实现的接口,否则没法用java操作数据库ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setDriverClass("com.mysql.jdbc.Driver");dataSource.setUser("root");dataSource.setPassword("开机密码");dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/hanshangping");//下面两行设置数据库连接池中只有一个数据库连接对象,initial和max都得设置为1dataSource.setInitialPoolSize(1);dataSource.setMaxPoolSize(1);Connection connection = dataSource.getConnection();Object inner = getInner(connection);//因为设置了数据库连接池中就一个对象,所以如果前面的连接不关闭,后面要想获取连接就会阻塞,即程序卡住了//如果设置了多个对象,则不关闭的话不推荐(占用内存)但是不会出错connection.close();Connection connection1 = dataSource.getConnection();System.out.println(connection);System.out.println(connection1);System.out.println(connection==connection1);// Object inner = getInner(connection); //代理类的close方法中会将被代理对象inner置为null,进而产生空指针异常,所以要在close之前就获取Object inner1 = getInner(connection1);System.out.println(inner.getClass().getName());System.out.println(inner1.getClass().getName());System.out.println(inner==inner1);}public static Object getInner(Object connection){Object result=null;Field field=null;try {field = connection.getClass().getDeclaredField("inner");//开启权限field.setAccessible(true);//获取传入的NewProxyConnection类中被代理的Connection对象result=field.get(connection);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}return result;}}com.mchange.v2.c3p0.impl.NewProxyConnection@769c9116 [wrapping: null]com.mchange.v2.c3p0.impl.NewProxyConnection@6aceb1a5 [wrapping: com.mysql.jdbc.JDBC4Connection@2d6d8735]falsecom.mysql.jdbc.JDBC4Connectioncom.mysql.jdbc.JDBC4Connectiontrue
- 由于设置了数据库连接池中只有一个连接对象(原生的mysql连接对象com.mysql.jdbc.JDBC4Connection,而不是代理对象com.mchange.v2.c3p0.impl.NewProxyConnection),所以当我们先开一个连接再关闭再开一个连接,两次连接对应的原生连接对象必然是同一个,而代理对象则就不是(每次都new)
- 如果不进行close就会阻塞,因为就一个连接资源,上一个没释放,下一个就只能阻塞
- 代理类NewProxyConnection中的close方法会将其中的被代理对象Connection inner置为null
当我把数据库连接池的参数设置为2,并且把close方法去掉,其他不变的打印结果为:
com.mchange.v2.c3p0.impl.NewProxyConnection@18ef96 [wrapping: com.mysql.jdbc.JDBC4Connection@6956de9]com.mchange.v2.c3p0.impl.NewProxyConnection@769c9116 [wrapping: com.mysql.jdbc.JDBC4Connection@6aceb1a5]falsecom.mysql.jdbc.JDBC4Connectioncom.mysql.jdbc.JDBC4Connectionfalse
可以看出两次的原生连接对象都是不同的,符合逻辑
2.1不适用数据库连接池的情况
package com.zhanglei.jdbc;import org.junit.Test;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;/*** ClassName:JdbcTest01* Package:com.zhanglei.jdbc* Description:** @Date:2021/8/2 10:47* @Author:zhanglei@3417529439@qq.com*/public class JdbcTest01 {@Testpublic void test() throws ClassNotFoundException, SQLException {//1.forName有返回值不一定需要接收啊,加载了这个类后会注册到DriverManager里面去的,后面getConnection自己会去匹配的,用不着你去操心Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/my1", "root", "56785");String sql="create table zhanglei_jdbc01 (id int, name varchar(32), price double ,introdution text)";Statement statement = connection.createStatement();statement.execute(sql);statement.close();connection.close();System.out.println("~~成功~~");}}
上面的com.mysql.jdbc.Driver也是需要导入mysql-connector-java这个依赖
然后用的是java自带的DriverManager进行数据库连接
而不是使用数据库连接池的datasource
