博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java数据库连接池 学习笔记
阅读量:4029 次
发布时间:2019-05-24

本文共 8030 字,大约阅读时间需要 26 分钟。

转自:http://blog.csdn.net/tobetheender/article/details/52841983

背景

对于一个简单的应用,由于对于数据库的访问不是很频繁。这时可以简单地在需要访问数据库时,就新创建一个连接,用完后就关闭它,这样做也不会带来什么明显的性能上的开销。但是对于一个复杂的数据库应用,情况就完全不同了。频繁的建立、关闭连接,会极大的减低系统的性能,因此对于连接的使用成了系统性能的瓶颈。

正是由于以上原因,数据库连接池技术出现了!!

数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。


数据库连接池优点:

1. 资源重用

由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。

2. 更快的系统响应速度

数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。

3. 新的资源分配手段

对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术,几年钱也许还是个新鲜话题,对于目前的业务系统而言,如果设计中还没有考虑到连接池的应用,那么…….快在设计文档中加上这部分的内容吧。某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。

4. 统一的连接管理,避免数据库连接泄漏

在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用连接。从而避免了常规数据库连接操作中可能出现的资源泄漏。


数据库连接池技术实现

目前数据库连接池技术实现常见有三种方式

  • 自定义数据库连接池
  • DBCP连接池
  • C3P0连接池

方式一:自定义数据库连接池

程序实现思路 
1.指定“初始化连接数目” (App启动时,就执行创建) 
2.指定“最大连接数” 
3.指定“当前使用连接数” (不能超出最大连接数)

代码实现思路 
1.MyPool. 连接池 
2.指定全局变量:初始化数目,最大连接数,当前连接数,连接池集合 
3.构造方法:循环创建3个连接 
4.写一个创建连接的方法 
5.获取连接 
判断:池中有连接,直接连 
池中没有连接,判断是否达到最大的连接数:达到,抛出异常;没有达到,创建新连接 
6.释放连接,连接池放回集合中

代理 
如果对某个接口中的某个指定的方法的功能进行扩展,而不想实现接口里所有方法,可以使用(动态)代理模式! 
Java中代理模式:静态/动态/Cglib代理() 
使用动态代理,可以监测接口中方法的执行!

如何对Connection对象,生成一个代理对象: 
|–Proxy 
static Object newProxyInstance( 
ClassLoader loader, 当前使用的类加载器 
Class[] interfaces, 目标对象(Connection)实现的接口类型 
InvocationHandler h 事件处理器:当执行上面接口中的方法的时候,就会自动触发事件处理器代码,把当前执行的方法(method)作为参数传入。 
)

详细代码

/** * 自定义连接池, 管理连接 * 代码实现:    1.  MyPool.java  连接池类,       2.  指定全局参数:  初始化数目、最大连接数、当前连接、   连接池集合    3.  构造函数:循环创建3个连接    4.  写一个创建连接的方法    5.  获取连接    ------>  判断: 池中有连接, 直接拿     ------>                池中没有连接,    ------>                 判断,是否达到最大连接数; 达到,抛出异常;没有达到最大连接数,            创建新的连接    6. 释放连接     ------->  连接放回集合中(..) * */public class MyPool {
private int init_count = 3; // 初始化连接数目 private int max_count = 6; // 最大连接数 private int current_count = 0; // 记录当前使用连接数 // 连接池 (存放所有的初始化连接) private LinkedList
pool = new LinkedList
(); //1. 构造函数中,初始化连接放入连接池 public MyPool() { // 初始化连接 for (int i=0; i
0){ return pool.removeFirst(); } // 3.2 连接池中没有连接: 判断,如果没有达到最大连接数,创建; if (current_count < max_count) { // 记录当前使用的连接数 current_count++; // 创建连接 return createConnection(); } // 3.3 如果当前已经达到最大连接数,抛出异常 throw new RuntimeException("当前连接已经达到最大连接数目 !"); } //4. 释放连接 public void realeaseConnection(Connection con) { // 4.1 判断: 池的数目如果小于初始化连接,就放入池中 if (pool.size() < init_count){ pool.addLast(con); } else { try { // 4.2 关闭 current_count--; con.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } public static void main(String[] args) throws SQLException { MyPool pool = new MyPool(); System.out.println("当前连接: " + pool.current_count); // 3 // 使用连接 pool.getConnection(); pool.getConnection(); Connection con4 = pool.getConnection(); Connection con3 = pool.getConnection(); Connection con2 = pool.getConnection(); Connection con1 = pool.getConnection(); // 释放连接, 连接放回连接池// pool.realeaseConnection(con1); /* * 希望:当关闭连接的时候,要把连接放入连接池!【当调用Connection接口的close方法时候,希望触发pool.addLast(con);操作】 * 把连接放入连接池 * 解决1:实现Connection接口,重写close方法 * 解决2:动态代理 */ con1.close(); // 再获取 pool.getConnection(); System.out.println("连接池:" + pool.pool.size()); // 0 System.out.println("当前连接: " + pool.current_count); // 3 }}
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

方式二:DBCP连接池

DBCP 是 Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:

  • Commons-dbcp.jar:连接池的实现
  • Commons-pool.jar:连接池实现的依赖库

Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。核心类:BasicDataSource

详细代码

public class App_DBCP {
@Test // 配置方式实现连接池,便于维护 public void testProp() throws Exception { // 加载prop配置文件 Properties prop = new Properties(); // 获取文件流 InputStream inStream = App_DBCP.class.getResourceAsStream("db.properties"); // 加载属性配置文件 prop.load(inStream); // 根据prop配置,直接创建数据源对象 DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop); // 获取连接 Connection con = dataSouce.getConnection(); con.prepareStatement("delete from admin where id=4").executeUpdate(); // 关闭 con.close(); }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

配置文件db.properties

  • url=jdbc:mysql:///jdbc_demo 
    driverClassName=com.mysql.jdbc.Driver 
    username=root 
    password=root 
    initialSize=3 
    maxActive=6 
    maxIdle=3000

方式三:C3P0连接池

C3P0连接池,最常用的连接池技术!Spring框架,默认支持C3P0连接池技术! 
C3P0连接池的核心jar包

  • c3p0-0.9.1.2.jar

核心类:CombopooledDataSource

实现步骤: 
1. 下载,引入jar文件: c3p0-0.9.1.2.jar 
2. 使用连接池,创建连接 
a) 硬编码方式 
b) 配置方式(xml)

具体代码

public class App {
@Test //XML配置方式,使用C3P0连接池管理连接 public void testXML() throws Exception { // 创建c3p0连接池核心工具类 // 自动加载src下c3p0的配置文件【c3p0-config.xml】 ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置 // 获取连接 Connection con = dataSource.getConnection(); // 执行更新 con.prepareStatement("delete from admin where id=5").executeUpdate(); // 关闭 con.close(); }}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

配置文件c3p0-config.xml

jdbc:mysql://localhost:3306/jdbc_demo
com.mysql.jdbc.Driver
root
root
3
6
1000
jdbc:mysql://localhost:3306/jdbc_demo
com.mysql.jdbc.Driver
root
root
3
6
1000

你可能感兴趣的文章
spring JdbcTemplate 的若干问题
查看>>
Servlet和JSP的线程安全问题
查看>>
GBK编码下jQuery Ajax中文乱码终极暴力解决方案
查看>>
jQuery性能优化指南
查看>>
Oracle 物化视图
查看>>
Multi-Task Networks With Universe, Group, and Task Feature Learning-阅读笔记
查看>>
A Survey of Zero-Shot Learning: Settings, Methods, and Applications-阅读笔记
查看>>
Cross-Domain Review Helpfulness Prediction -论文阅读
查看>>
NLP数据增强方法-(一)
查看>>
BERT+实体-百度ERNIE优化了啥
查看>>
NLP数据增强方法-动手实践
查看>>
学习让机器学会学习-Meta Learning课程笔记-1
查看>>
学习让机器学会学习-Meta Learning课程笔记-2
查看>>
RNN及其变种LSTM/GRU/SRU
查看>>
我还不知道Attention有哪些-公式代码都带你搞定
查看>>
自学习-怎么让对话助手越来越强
查看>>
BERT-flow:bert的向量表达是SOTA吗?
查看>>
Preprocessing data-sklearn数据预处理
查看>>
Java实现Oracle到MySQL的表迁移
查看>>
子类A继承父类B, A a = new A(); 则父类B构造函数、父类B静态代码块、父类B非静态代码块、子类A构造函数、子类A静态代码块、子类A非静态代码块 执行的先后顺序是?
查看>>