【学习笔记】数据库连接池
数据库的连接,执行到释放,过程十分浪费系统资源
所以出现了一种技术叫做:池化技术
池化技术:准备一些预先的资源,过来就连接预先准备好的资源
最小连接数:根据业务来调整,常用连接数在100个左右,最小连接数为100即可
最大连接数:业务最高承载上限
超过了最大连接数就需要排队等待,等别人用完,才能再去使用
等待超时:如果一个业务等待的时间超过某个时间,就不让他等待了,自动结束
编写连接池,只需要实现一个接口:DataSource
目前比较知名的实现类:开源数据源实现
-
DBCP
-
C3P0
-
Druid 阿里巴巴
使用了这些数据库连接池后,我们在项目开发中就不需要编写连接数据库的代码了
DBCP
需要导入的jar包:
commons-dbcp-1.4.jar 、commons-pool-1.6.jar
-
新建配置文件 dbcp.properties
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true username=root password=123456 #<!-- 初始化连接 --> initialSize=10 #最大连接数量 maxActive=50 #<!-- 最大空闲连接 --> maxIdle=20 #<!-- 最小空闲连接 --> minIdle=5 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 --> maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;】 #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。 connectionProperties=useUnicode=true;characterEncoding=UTF8 #指定由连接池所创建的连接的自动提交(auto-commit)状态。 defaultAutoCommit=true #driver default 指定由连接池所创建的连接的只读(read-only)状态。 #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix) defaultReadOnly= #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED
-
编写dbcp工具类
package com.lesson05.utils; import org.apache.commons.dbcp.BasicDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JdbcUtils_DBCP { private static DataSource dataSource = null; static{ try{ //读取配置文件 InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcp.properties"); Properties properties = new Properties(); properties.load(in); //创建数据源 使用工厂模式 dataSource = BasicDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } //获取连接 public static Connection getConnection() throws SQLException { return dataSource.getConnection(); //从数据源中获取连接 } //关闭连接 public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException { if (rs != null){ rs.close(); } if (st != null){ st.close(); } if (rs != null){ rs.close(); } } }
与之前的区别就是,不用自己创建连接,直接从数据源中获取连接
使用工厂模式创建数据源,从配置文件中获得数据库的信息
-
测试
package com.lesson05; import com.lesson02.utils.JdbcUtils; import com.lesson05.utils.JdbcUtils_DBCP; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Date; public class TestDbcp { public static void main(String[] args) throws SQLException { Connection connection = JdbcUtils_DBCP.getConnection(); //使用 ? 占位符 代替参数 String sql = "insert into users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`)values (?,?,?,?,?)"; //先预编译sql PreparedStatement ps = connection.prepareStatement(sql); //手动给参数赋值 ps.setInt(1,5); //第一个参数是表示第几个占位符即第几个? 第二个参数是具体的值 ps.setString(2,"xiaohong"); ps.setString(3,"123561"); ps.setString(4,"123456@123.com"); ps.setDate(5,new java.sql.Date(new Date().getTime())); int i = ps.executeUpdate(); if (i>0){ System.out.println("插入成功"); } JdbcUtils_DBCP.release(connection,ps,null); } }
C3P0
需要导入的jar包:
c3p0-0.9.5.5.jar、mchange-commons-java-0.2.19.jar
-
配置文件 c3p0config.xml
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- c3p0的缺省(默认)配置 如果在代码中ComboPooledDataSource ds=new ComboPooledDataSource();这样写就表示使用的是c3p0的缺省(默认) --> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC</property> <property name="user">root</property> <property name="password">123456</property> <property name="acquiredIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </default-config> <!-- c3p0的命名配置 如果在代码中ComboPooledDataSource ds=new ComboPooledDataSource("MySQL");这样写就表示使用的是name是MySQL --> <name-config name="MySQL"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC</property> <property name="user">root</property> <property name="password">123456</property> <property name="acquiredIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </name-config> </c3p0-config>
它里面的有两个方法,一个有参数,一个没有参数,调用时,带参数就执行上面的那个,不带参数就执行下面那个。
-
c3p0工具类
package com.lesson05.utils; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JdbcUtils_C3P0 { private static DataSource dataSource = null; static{ try{ //第一种写法读取配置文件 dataSource = new ComboPooledDataSource("MySQL"); //第二种写法 代码版配置 // dataSource = new ComboPooledDataSource(); // dataSource.setDriverClass(); // dataSource.setUser(); } catch (Exception e) { e.printStackTrace(); } } //获取连接 public static Connection getConnection() throws SQLException { return dataSource.getConnection(); //从数据源中获取连接 } //关闭连接 public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException { if (rs != null){ rs.close(); } if (st != null){ st.close(); } if (rs != null){ rs.close(); } } }
测试与上面相同,只是把工具类的名字改一下就好。
无论用什么数据源,本质还是一样的,DataSource接口不变,方法就不会变