赞
踩
JDBC开发流程
数据库连接对象是通过 DriverManager 得到的,每次获取都要向数据库申请获取连接,并验证用户名、密码,执行完 SQL 语句后,断开连接,这样的方式会造成资源的浪费,因为连接对象只使用了一次就释放掉了,下一次连接还要继续向数据库申请,相当于用一部手机打电话,打了一通电话就把手机扔掉了,需要下一次通话时,在买一部,然后在打,资源没有得到很好的利用。
为了解决这一问题,数据库连接池出现了,其基本思想是为数据库建立一个连接池,预先向连接池存入一些连接对象,当需要获取连接时,只需要从连接池中取出一个连接,用完之后在放回到池中,供下一次连接继续使用,这样资源就得到了很好的复用,使一个连接对象可以被重复的使用,而不需要重新创建。
当数据库连接池中没有多余的连接对象时,线程就会进入等待状态,等待其它线程释放连接对象后在使用。
JDBC 数据库连接池是使用 javax.sql.DataSource 接口来实现的,是由 java 官方提供的,连接池是一种思想,接口是一种抽象的功能,具体的实现还是得自己写。但是如果是自己写连接池的话,太麻烦,需要自己写底层代码,所以我们可以使用第三方写好的工具。
常用的第三方连接池工具:c3p0、dhcp等
使用 c3p0 工具,有三种实现方法:
通过硬编码方式设置驱动类及用户名、密码等。
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // 创建 ComboPooledDataSource 对象,该对象间接实现了 java 官方提供的 DataSource 接口 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setDriverClass("org.mariadb.jdbc.Driver"); comboPooledDataSource.setJdbcUrl("jdbc:mariadb://localhost:3306/dbtest?useUnicode=true&characterEncoding=UTF-8"); comboPooledDataSource.setUser("root"); comboPooledDataSource.setPassword("password"); // 设置初始化连接数 comboPooledDataSource.setInitialPoolSize(20); // 设置最小连接数,当连接池还有2个的时候,就开始申请连接数 comboPooledDataSource.setMinPoolSize(2); // 设置最大连接数,最多只能有 40 个连接 comboPooledDataSource.setMaxPoolSize(40); // 当连接数不够用时,一次向数据库申请多少个连接 comboPooledDataSource.setAcquireIncrement(5); // 只是对连接做了优化,剩下的操作不变 String sql = "select * from student"; connection = comboPooledDataSource.getConnection(); preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()){ Integer id = resultSet.getInt(1); String name = resultSet.getString(2); Double score = resultSet.getDouble(3); Date birthday = resultSet.getDate(4); System.out.println(id + name + score + birthday); } } catch (PropertyVetoException e) { e.printStackTrace(); } catch (SQLException e){ e.printStackTrace(); } finally { try { resultSet.close(); preparedStatement.close(); // 这里并不是把连接关闭了,而是释放到连接池里,等待下一次继续使用 connection.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } }
通过 xml 配置文件设置
c3p0-config.xml:
文件名是固定的,放在 src 根目录下
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <default-config> <!-- 数据库驱动名 --> <property name="driverClass">org.mariadb.jdbc.Driver</property> <!-- 数据库的url --> <!-- 在 xml 文件中,& 符号需要进行转义,使用 & 来代替 & --> <property name="jdbcUrl">jdbc:mariadb://localhost:3306/dbtest?useUnicode=true&characterEncoding=UTF-8</property> <property name="user">root</property> <property name="password">password</property> <!--初始化连接数,取值应在minPoolSize与maxPoolSize之间 --> <property name="initialPoolSize">20</property> <!--当连接池中的连接耗尽的时候 c3p0 一次同时获取的连接数 --> <property name="acquireIncrement">5</property> <!-- 设置最小连接数,当连接池还有2个的时候,就开始申请连接数--> <property name="minPoolSize">2</property> <!-- 设置最大连接数,最多只能有 40 个连接--> <property name="maxPoolSize">40</property> <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 --> <property name="acquireRetryAttempts">30</property> <!--两次连接中间隔时间,单位毫秒。Default: 1000 --> <property name="acquireRetryDelay">1000</property> <!--连接关闭时默认将所有未提交的操作回滚。Default: false --> <property name="autoCommitOnClose">false</property> <!--每60秒检查所有连接池中的空闲连接。Default: 0 --> <property name="idleConnectionTestPeriod">0</property> <!-- 连接超时时间, default: 0。如果是0,表示无限等待 --> <property name="checkoutTimeout">0</property> </default-config> <named-config name="testc3p0"> ... ... </named-config> </c3p0-config>
java 文件:
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { /** * 这个方法提供一个无参构造,一个有参构造 * 无参构造默认读取配置文件中的 <default-config> 节点中的内容 * 有参构造读取 <named-config name="testc3p0"> 节点中的内容,传入的参数为 name 的 value */ // 无参构造 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); //有参构造 //ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("testc3p0"); connection = comboPooledDataSource.getConnection(); preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()){ Integer id = resultSet.getInt(1); String name = resultSet.getString(2); Double score = resultSet.getDouble(3); Date birthday = resultSet.getDate(4); System.out.println(id + name + score + birthday); } } catch (SQLException e) { e.printStackTrace(); } finally { try { resultSet.close(); preparedStatement.close(); // 这里并不是把连接关闭了,而是释放到连接池里,等待下一次继续使用 connection.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } }
使用 properties 配置文件
c3p0 会自动解析 properties 文件
c3p0.properties:
文件名固定,也是放到 src 目录下
c3p0.driverClass=org.mariadb.jdbc.Driver
c3p0.jdbcUrl=jdbc:mariadb://localhost:3306/dbtest?useUnicode=true&characterEncoding=UTF-8
c3p0.user=root
c3p0.password=password
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); connection = comboPooledDataSource.getConnection(); preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); while (resultSet.next()){ Integer id = resultSet.getInt(1); String name = resultSet.getString(2); Double score = resultSet.getDouble(3); Date birthday = resultSet.getDate(4); System.out.println(id + name + score + birthday); } } catch (SQLException e) { e.printStackTrace(); } finally { try { resultSet.close(); preparedStatement.close(); // 这里并不是把连接关闭了,而是释放到连接池里,等待下一次继续使用 connection.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。