数据库连接池

前述:

  对之前JDBC的操作,不管是原始的操作步骤,还是JDBCUtils工具类的写法,都存在一个严重的问题:每次我们都需要去创建一个连接对象,然后再释放掉资源的操作。

  从效率和内存的角度,这种重复创建和释放的操作方式是不可取的。那么该如何优化?

  既然知道了问题是出现在重复创建和释放的操作上,那我们便可以对症下药--让重复不再重复。

  于是,结合线程池的思想,我们也可以创建一个容器来存放一定数量的数据库连接对象,在使用时获取,在关闭时归还。---我们称之为数据库连接池

 

一、数据库连接池

 1.1 概述

    存放数据库连接的容器(集合)。

    作用:

    • 高效率(提升系统响应效率)
    • 节约资源(资源重用)
    • 避免数据库连接遗漏(释放空闲时间超过最大空闲时间的数据库连接)

 1.2 代码实现

    接口标准:javax.sql.DataSource

    • 获取连接:getConnection()
    • 归还连接:Connection.close()。  // 如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了,而是归还连接。

 小贴士:一般我们不去实现它,由数据库厂商来实现,比如:

  • C3P0:数据库连接池技术
  • Druid(竹歪的:德鲁伊):数据库连接池实现技术(由阿里巴巴提供的)

 

二、C3P0 数据库连接池技术

 2.1 步骤

    1. 导入jar包 (两个: c3p0-0.9.5.2.jar、mchange-commons-java-0.2.12.jar)
    2. 定义配置文件:
      * 名称:c3p0.properties 或者 c3p0-config.xml
      * 路径:直接将文件放在src目录下即可。
    3. 创建核心对象:数据库连接池对象 ComboPooledDataSource
    4. 获取连接:getConnection

 2.2 代码实现

1
2
3
4
// 1. 创建数据库连接池对象
DataSource ds  = new ComboPooledDataSource();
// 2. 获取连接对象
Connection conn = ds.getConnection();

 

三、Druid 数据库连接池实现技术(由阿里巴巴提供)

 3.1 步骤

    1. 导入jar包 druid-1.0.9.jar
    2. 定义配置文件:
      * 是properties形式的,如druid.properties
      * 可以叫任意名称,可以放在任意目录下
    3. 加载配置文件。Properties
    4. 获取数据库连接池对象:通过工厂类来获取 DruidDataSourceFactory
    5. 获取连接:getConnection

 3.2 代码实现

1
2
3
4
5
6
7
8
// 1.加载配置文件
Properties pro = new Properties();
InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
// 2.获取连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
// 3.获取连接对象
Connection conn = ds.getConnection();

 

四、重新定义JDBCUtils工具类

 4.1 步骤

    1. 定义一个工具类 JDBCUtils
    2. 提供静态代码块加载配置文件,初始化连接池对象
    3. 提供方法
      *  获取连接方法:通过数据库连接池获取连接
      *  释放资源
      *  获取连接池的方法

 4.2 代码实现(使用Druid连接池)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
public class JDBCUtils {
 
    //1.定义成员变量 DataSource
    private static DataSource ds ;
 
    static{
        try {
            //1.加载配置文件
            Properties pro = new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 获取连接
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
 
    /**
     * 释放资源
     */
    public static void close(Statement stmt,Connection conn){
       /* if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();   //归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }*/
 
       close(null,stmt,conn);
    }
    /**
     * 释放资源
     */
    public static void close(ResultSet rs , Statement stmt, Connection conn){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();   //归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
     
    /**
     * 获取连接池方法
     */
    public static DataSource getDataSource(){
        return ds;
    }
             
}

  // 当前文件的路径

System.out.println(System.getProperty("user.dir"));

 

五、Spring JDBC

 5.1 概述

    Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发。

 5.2 步骤

    1. 导入相关的jar包;(如:spring-jdbc-5.0.0.RELEASE.jar等)
    2. 创建JdbcTemplate对象。依赖于数据源DataSource
      * JdbcTemplate template = new JdbcTemplate(ds);
    3. 调用JdbcTemplate的方法来完成CRUD的操作
      * update():执行DML(增、删、改)语句。
      * queryForMap():查询结果将结果集封装为map集合。
        * 注意:查询的结果集长度只能是1,将列名作为key,将值作为value, 将这条记录封装为一个map集合。
      * queryForList():查询结果将结果集封装为list集合。
        * 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中。
      * query():查询结果,将结果封装为JavaBean对象。
      * query的参数:RowMapper
        * 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装。
        * new BeanPropertyRowMapper<类型>(类型.class)
      * queryForObject:查询结果,将结果封装为对象。
        * 一般用于聚合函数的查询

 


 面试题:数据库连接池的工作机制是什么?

  J2EE服务器启动时会建立一定数量的连接池,并一直维持不少于此数目的池连接。
  客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其标记为忙。
  如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量由配置参数决定。
  当使用的池连接调用完成后,池驱动程序将此连接标记为闲,其他调用就可以使用这个连接。
  实现方式,返回的Connection是原始Connection的代理,代理Connection的close方法不是真正关闭连接,而是把它代理的Connection对象还回到连接池中。

 

posted @   九点的太阳  阅读(197)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示