连接池
1、连接池介绍
没有连接池的现状
首先我们通过画图的形式来分析一下我们目前所学的jdbc程序的结构。
说明:以前使用的jdbc的缺点:
1、操作数据库都需要创建连接,操作完成还需要关闭连接
2、创建连接和关闭连接需要可能比执行sql需要的时间都长
3、一个网站需要高频繁的访问数据库,如果短时间频繁的访问数据库服务器,就容易造成服务器的宕机,即死机。
连接池解决现状问题的原理
注意:
通过画图分析得出:当前的jdbc程序每次访问数据库都需要创建一个新的连接,访问完毕之后,还需要释放资源。那么在这样的一个过程中,连接的创建和销毁所消耗的资源是远远大于我们发送sql并执行的时间的。基于这样的情况,我们发现我们的jdbc程序将大量的资源浪费在了连接的创建和销毁上。
举例:就像在上海坐地铁,就一站2分钟的路程,往往在买地铁票的过程需要等待至少10分钟以上的时间。这样是不合理的。所以我们 需要对这样的结构进行优化。
思考上面的结构,大部分的时间浪费在了创建和销毁上。那么我们能不能实现将这些连接回收和利用呢?这样我们就不需要不停的创建和销毁了。只需要创建一次,放在指定的地方。当我们使用的时候,直接从里面拿就行了。用完放回原来的地方。不去销毁,当我再次使用的时候,去拿就行了。而这样的解决方案就是我们需要的。
优化后的结构如下:
说明:首先创建一定数量的连接,然后放到指定的地方。当我们需要获取连接的时候,直接从指定的地方获取。用完了,我们再将连接放回去。这样就能将我们连接的回收利用。并且不用花费大量时间在创建和销毁连接上。
解决方案如下图所示:
连接池好处
连接池中保存了一些数据库连接,这些连接是可以重复使用的。节省数据库的资源消耗。
常用连接池的介绍
javax.sql.DataSource
表示数据库连接池,DataSource本身只是Sun公司提供的一个接口,没有具体的实现,它的实现由连接池的数据库厂商去实现。我们只需要学习这个工具如何使用即可。
该接口如下:
public interface DataSource {
Connection getConnection();
}
常用的连接池实现组件有以下这些:
- 阿里巴巴-德鲁伊Druid连接池:Druid是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池、插件框架和SQL解析器组成。该项目主要是为了扩展JDBC的一些限制,可以让程序员实现一些特殊的需求。
- C3P0是一个开源的JDBC连接池,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0有自动回收空闲连接功能。
- DBCP(DataBase Connection Pool)数据库连接池,是Apache上的一个Java连接池项目。dbcp没有自动回收空闲连接的功能。
小结
连接池的好处?
连接池内部会保存好一些连接,这些连接可以反复使用,提高连接的使用率,降低数据库资源消耗
连接池的原理?
1.创建连接池时,连接池内部就会创建一些连接
2.当需要使用连接时,就直接从连接池里面取出连接
3.当连接使用完毕时,重新放回连接池
2、Druid连接池
目标
能够掌握Druid连接池的使用
讲解
DRUID简介
Druid是阿里巴巴开发的号称为监控而生的数据库连接池(可以监控访问数据库的性能),Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。如:一年一度的双十一活动,每年春运的抢火车票。
DRUID连接池使用的jar包:druid-1.0.9.jar
Druid常用的配置参数
url | 数据库连接字符串jdbc:mysql://localhost:3306/数据库名 |
---|---|
username | 数据库的用户名 |
password | 数据库的密码 |
driverClassName | 驱动类名。根据url自动识别,这一项可配可不配,如果不配置druid会根据url自动识别数据库的类型,然后选择相应的数据库驱动名 |
initialSize | 初始化时建立的物理连接的个数。初始化发生在显式调用init方法,或者第一次获取连接对象时 |
maxActive | 连接池中最大连接数 |
maxWait | 获取连接时最长等待时间,单位是毫秒。 |
Druid连接池基本使用
API介绍
核心类:DruidDataSourceFactory
获取数据源的方法:使用com.alibaba.druid.pool.DruidDataSourceFactory类中的静态方法:
public static javax.sql.DataSource createDataSource(Properties properties)
创建一个连接池,连接池的参数使用properties中的数据
配置信息在properties属性对象中。
我们可以看到Druid连接池在创建的时候需要一个Properties对象来设置参数,所以我们使用properties文件来保存对应的参数。
Druid连接池的配置文件名称随便,放到src目录或者项目根目录下面加载
druid.properties
文件内容:
# 数据库连接参数
url=jdbc:mysql://localhost:3306/day05_db
username=root
password=123
driverClassName=com.mysql.jdbc.Driver
使用步骤
- 导入核心包druid-1.0.9.jar
- 在项目下创建一个properties文件,文件名随意,设置对应参数
-
加载properties文件的内容到Properties对象中
-
创建DRUID连接池,使用配置文件中的参数
-
从DRUID连接池中取出连接
-
执行SQL语句
-
关闭资源
案例代码
- 属性文件:在项目下新建一个druid配置文件,命名为:druid.properties
# 数据库连接参数
url=jdbc:mysql://localhost:3306/day05_db
username=root
password=123
driverClassName=com.mysql.jdbc.Driver
2.java代码
public class Demo03 {
public static void main(String[] args) throws Exception {
//加载properties文件的内容到Properties对象中
Properties info = new Properties();
//加载项目下的属性文件 相对项目根目录
// FileInputStream fis = new FileInputStream("druid.properties");
//相对src目录
InputStream fis = Test01.class.getClassLoader().getResourceAsStream("druid.properties");
//从输入流中加载属性
info.load(fis);
System.out.println(info);
//创建DRUID连接池,使用配置文件中的参数
DataSource dataSource = DruidDataSourceFactory.createDataSource(info);
//从DRUID连接池中取出连接
//Connection conn = dataSource.getConnection();
//System.out.println("conn = " + conn);
// 需求: 根据用户名和密码 查询用户信息
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获得连接
conn = dataSource.getConnection();
// 获得发送sql的对象
String sql = "select * from emp where name=? and city=?";
pstmt = conn.prepareStatement(sql);
// 如果有问号,需要 设置参数,注意:下标从1开始
pstmt.setString(1, "刘备");
pstmt.setString(2, "北京");
// 执行sql 获得结果
rs = pstmt.executeQuery();
// 处理结果
if (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String city = rs.getString("city");
System.out.println(id + ":::" + name + "===" + city);
} else {
System.out.println("没有查到对应的用户信息!");
}
} catch (Exception e) {
} finally {
// JDBCUtils.release(conn, pstmt, rs);
}
}
}
JDBC练习
1.需求
完成商品品牌数据的增删改查操作。
•查询:查询所有数据
•添加:添加品牌
•修改:根据 id修改
•删除:根据 id删除
2.环境搭建
•准备环境:1.创建项目 2.导入druid 和mysql驱动包 3.在src下面创建连接数据库的配置文件
Ø数据库表 tb_brand
Ø实体类 Brand
Ø测试用例
3.查询所有数据
1.获取Connection
2.定义SQL:select *** from tb_brand;
3.获取 PreparedStatement对象
4.设置参数:不需要
5.执行SQL
6.处理结果:List
7.释放资源
@Test
public void query() throws Exception{
Properties p = new Properties();
p.load(new FileInputStream("src\\druid.properties"));
DataSource ds = DruidDataSourceFactory.createDataSource(p);
//获取Connection
Connection conn = ds.getConnection();
//定义SQL:select * from tb_brand;
String sql = "select * from tb_brand";
//获取 PreparedStatement对象
PreparedStatement pst = conn.prepareStatement(sql);
//设置参数:不需要
//执行SQL
ResultSet rs = pst.executeQuery();
//处理结果:List<Brand>
ArrayList<Brand> list = new ArrayList<>();
while (rs.next()){
int id = rs.getInt("id");
String brandName = rs.getString("brand_name");
String companyName = rs.getString("company_name");
int ordered = rs.getInt("ordered");
String description = rs.getString("description");
int status = rs.getInt("status");
Brand brand = new Brand();
brand.setId(id);
brand.setBrandName(brandName);
brand.setCompanyName(companyName);
brand.setOrdered(ordered);
brand.setDescription(description);
brand.setStatus(status);
list.add(brand);
}
System.out.println("list = " + list);
//释放资源
rs.close();
pst.close();
conn.close();
}
4.添加
@Test
public void add() throws Exception{
Properties p = new Properties();
p.load(new FileInputStream("src\\druid.properties"));
DataSource ds = DruidDataSourceFactory.createDataSource(p);
//获取Connection
Connection conn = ds.getConnection();
String sql = "insert into tb_brand values(null,?,?,?,?,?)";
//获取 PreparedStatement对象
PreparedStatement pst = conn.prepareStatement(sql);
pst.setString(1,"苹果");
pst.setString(2,"apple");
pst.setInt(3,1);
pst.setString(4,"贵");
pst.setInt(5,0);
int count = pst.executeUpdate();
System.out.println("count = " + count);
//释放资源
pst.close();
conn.close();
}
5.修改
@Test
public void update() throws Exception{
Properties p = new Properties();
p.load(new FileInputStream("src\\druid.properties"));
DataSource ds = DruidDataSourceFactory.createDataSource(p);
//获取Connection
Connection conn = ds.getConnection();
String sql = "update tb_brand set brand_name = ?,company_name= ?,ordered= ?,description = ?,status= ? where id = ?";
//获取 PreparedStatement对象
PreparedStatement pst = conn.prepareStatement(sql);
pst.setString(1,"OPPO");
pst.setString(2,"OPPO");
pst.setInt(3,1);
pst.setString(4,"贵");
pst.setInt(5,0);
pst.setInt(6,3);
int count = pst.executeUpdate();
System.out.println("count = " + count);
//释放资源
pst.close();
conn.close();
}
6.删除
@Test
public void delete() throws Exception{
Properties p = new Properties();
p.load(new FileInputStream("src\\druid.properties"));
DataSource ds = DruidDataSourceFactory.createDataSource(p);
//获取Connection
Connection conn = ds.getConnection();
String sql = "delete from tb_brand where id = ?";
//获取 PreparedStatement对象
PreparedStatement pst = conn.prepareStatement(sql);
pst.setInt(1,4);
int count = pst.executeUpdate();
System.out.println("count = " + count);
//释放资源
pst.close();
conn.close();
}