JDBC连接------C3P0连接池
目录
1、为什么要用到连接池
2、连接池原理
3、C3P0连接池
总结
1、为什么要用到连接池
当一个用户要访问某个网站时,就需要频繁的使用数据库进行增删改查,每次增删改查操作都需要获取连接,如果说一个用户的频繁获取连接系统尚能接受,那么成千上万的用户浏览这个网站进行增删改查来获取连接 对系统来说将是一个巨大的负荷!为了解决这一问题,我们可以设计一个用来存放连接的池子,这个池子起名为连接池。连接池中存放一定数量的连接,当用户需要获取连接时,就从这个池子中获取,用完后关闭资源,再将连接放回连接池。如此,一个连接就可以被反复使用,大大降低系统的压力解决了建立数据库连接耗费资源和时间很多的问题,提高了性能。
2、连接池原理
具体的代码实现连接池此处不作赘述,只简单解释下连接池的拿连接·和还连接的原理。
市面上常用的连接池有很多,DBCP 、C3P0、BoneCP、Proxool、DDConnectionBroker、DBPool、XAPool、Primrose、SmartPool、MiniConnectionPoolManager及Druid等。Java为数据库连接池提供了公共的接口:javax.sql.DataSource ,各个厂商需要让自己的连接池实现这个接口。这也大大减小了程序员的开发成本。
连接池其实就是一个需要频繁拿连接,还连接的大容器。说白了连接池就是一个集合List<Connection>(因为是频繁的取还元素,所以这里集合更适合是LinkedList)。当用户访问时,先向容器中放入多个连接,当用户使用时,将连接获取出去,获取时连接就要从连接池中被拿走,此处用remove方法获取(不可以用get方法获取连接),remove方法返回值就是移除的内容,待用户使用完毕后,再将连接放回去(add)。这样即实现了连接池额功能,可以让集合中的连接反复使用,不需要多次创建新的连接。
3、C3P0连接池
C3P0连接池因为其配置简单,持续运行的稳定性很不错,在大并发量下的稳定性也有一定保证的优良特性,受到广大用户的欢迎。使用C3P0连接池需要用到架包和配置文件,需要配置文件和架包可以点击下面连接。
C3P0用到的jar包和配置文件。
配置文件为固定格式的XML文件c3p0-config.xml(3-1),配置文件必须放在项目的src文件夹下面,创建C3P0连接池后会被自动解析。
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<!--驱动 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!--连接 -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day03</property>
<!--用户名 -->
<property name="user">root</property>
<!-- 密码-->
<property name="password">root</property>
<!-- 连接池参数 -->
<!-- 初始化连接池连接数-->
<property name="initialPoolSize">5</property>
<!--连接池内最大连接数 -->
<property name="maxPoolSize">10</property>
<!--最大等待时间 -->
<property name="checkoutTimeout">2000</property>
<!--最大空闲回收时间 -->
<property name="maxIdleTime">1000</property>
</default-config>
</c3p0-config>
通过C3P0获取连接同样写在一个工具类里面,和前面原生方法获取连接的工具类基本一致,不同的是此处获取连接是在连接池中获取。代码如下(3-2)
package teacher.com.itheima.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
/*
通过getConnection方法 从连接池中 获取到java.sql.Connection接口的实现类对象
JDK提供了一个连接池的接口 java.sql.DataSource
方法
Connection getConnection() 从连接池中获取到连接对象
要想调用这个方法 就需要DataSource实现类对象 C3P0连接池实现了此接口
ComboPooledDataSource类实现了 DataSource接口 我们只需要创建这个类的对象
调用getConnection方法就是从连接池中获取了连接
*/
public class C3P0Utils {
//先私有化连接池变量
private static ComboPooledDataSource ds ;
//工具类固有写法,私有化构造方法
private C3P0Utils(){}
//在静态代码块中创建连接池
static{
try{
//创建连接池后会自动读取并解析项目的src目录下的c3p0-config.xml配置文件并自动的加载驱动
ds = new ComboPooledDataSource();
//对连接池进行配置,此处配置和配置文件的配置完全一样,是配置连接池的另一种方式,
// 两种配置方式取其一即可,一般用配置文件
// 在已经有配制文件的情况下会优先解析此处java代码的配置。
//此处配置和
// ds.setDriverClass("com.mysql.jdbc.Driver");
// ds.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/day04");
// ds.setUser("root");
// ds.setPassword("root");
//可选配置
// ds.setInitialPoolSize(10);
//最大连接数
// ds.setMaxPoolSize(100);
//最大等待时间
// ds.setCheckoutTimeout(10000);
//最大空闲回收时间
// ds.setMaxIdleTime(1000000);
}catch (Exception e){
e.printStackTrace();
}
}
//获取连接池对象 在后面是有DBUtils时会用到
public static DataSource getDataSouce(){
return ds;
}
//从连接池中获取连接对象
public static Connection getConnection() throws SQLException {
Connection con = ds.getConnection();//实现类对象
return con;
}
//关闭资源,虽然是close但是是还回连接到连接池中
public static void close(Connection con, Statement stat, ResultSet rs){
try {
if(con!=null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(stat!=null)
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(rs!=null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
至此,一个使用C3P0创建连接池,获取连接的工具类已经完成,后面调用连接只需要通过C3P0.getConnection()的方法调用即可(3-3),和原生JDBC连接调用工具类的方法一样。
package teacher.com.itheima03;
import teacher.com.itheima.bean.User;
import teacher.com.itheima.utils.C3P0Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/*
查询users表中所有数据
将每条数据封装到一个USer对象中
将对象放入一个list集合中
*/
public class Test_C3P0Utils {
public static void main(String[] args) throws SQLException {
//根据c3p0工具类获取连接对象
Connection con = C3P0Utils.getConnection();
//根据连接获取执行sql语句对象
String sql = "select * from students";
PreparedStatement ps = con.prepareStatement(sql);
//执行sql语句;
ResultSet rs = ps.executeQuery();
//定义一个集合 遍历结果集 获取内容
List<User> list = new ArrayList<>();
while(rs.next()){
int stuid = rs.getInt("stuid");
String stu_name = rs.getString("stu_name");
int classid = rs.getInt("classid");
String sex = rs.getString("sex");
int book = rs.getInt("book");
// //将数据封装到User对象中
User u = new User(stuid,stu_name,classid,sex,book);
将User对象添加到集合中
list.add(u);
}
System.out.println(list);
//关闭资源
C3P0Utils.close(con,ps,rs);
// con.close();
}
}
总结
C3P0创建连接池获取连接的方法解决了用户频繁获取连接对系统资源造成的浪费,但是Test_C3P0Utils类中调用工具类获取连接执行sql的代码过于繁杂的情况依然存在,下一篇文章会利用工具类DBUtils来对这些操作进行简化。
能力尚浅,有待进步,如有不足,不吝赐教!