JDBC实例--工具类升级,使用Apache DBCP连接池重构DBUtility,让连接数据库更有效,更安全
直接使用JDBC访问数据库时,需要避免以下隐患:
1. 每一次数据操作请求都需要建立数据库连接、打开连接、存取数据和关闭连接等步骤。而建立和打开数据库连接是一件既耗资源又费时的过程,如果频繁发生这种数据库操作,势必会使系统性能下降。
2. 连接对象代表着数据库系统的连接进程,是有限的资源。如果系统的使用用户非常多,有可能超出数据库服务器的承受极限,造成系统的崩溃。
数据库连接池是解决上述问题最常用的方法。所谓连接池,即可以创建并持有数据库连接的组件。连接池可以预先创建并封装一些连接对象并将其缓存起来,当需要使用连接对象时可以向连接池“借”一个连接,用完之后将其“归还”到连接池中。
数据库连接池的主要功能如下:
1. 连接池对象的创建和释放。
2. 服务器启动时,创建指定数量的数据库连接。
3. 为用户请求提供可用连接。如果没有空闲连接,且连接数没有超出最大值,创建一个新的数据库连接。
4. 将用户不再使用的连接标识为可用连接,等待其他用户请求。
5. 当空闲的连接数过多时,释放连接对象。
连接池组件一般都需要实现JDBC规范中的javax.sql.DataSource接口。DataSource接口定义了获取连接的方法getConnection方法。
常用的连接池组件有DBCP、c3p0和proxool等,我这里是以Apache的DBCP组件为例来实现数据库连接池。
新建一个java项目,以及配置文件,如下:

在当前工程下,导入使用DBCP组件所需的jar包,包括commons-dbcp.jar以及commons-pool.jar两个jar包,这两个jar包的名字可能会因为版本的不同,名字的最后为版本信息,例如:commons-dbcp-1.2.1.jar。
工具类DBUtility:
package com.daliu.jdbc; import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties; import org.apache.commons.dbcp.BasicDataSource;
/**
* 工具类
* @author daliu_it
*
*/
public class DBUtility {
private static BasicDataSource dataSource = null; public DBUtility() {
}
public static void init() { Properties dbProps = new Properties();
// 取配置文件可以根据实际的不同修改
try {
dbProps.load(DBUtility.class.getClassLoader().getResourceAsStream(
"com/daliu/jdbc/db.properties"));
} catch (IOException e) {
e.printStackTrace();
} try {
String driveClassName = dbProps.getProperty("jdbc.driverClassName");
String url = dbProps.getProperty("jdbc.url");
String username = dbProps.getProperty("jdbc.username");
String password = dbProps.getProperty("jdbc.password"); String initialSize = dbProps.getProperty("dataSource.initialSize");
String minIdle = dbProps.getProperty("dataSource.minIdle");
String maxIdle = dbProps.getProperty("dataSource.maxIdle");
String maxWait = dbProps.getProperty("dataSource.maxWait");
String maxActive = dbProps.getProperty("dataSource.maxActive"); dataSource = new BasicDataSource();
dataSource.setDriverClassName(driveClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password); // 初始化连接数
if (initialSize != null)
dataSource.setInitialSize(Integer.parseInt(initialSize)); // 最小空闲连接
if (minIdle != null)
dataSource.setMinIdle(Integer.parseInt(minIdle)); // 最大空闲连接
if (maxIdle != null)
dataSource.setMaxIdle(Integer.parseInt(maxIdle)); // 超时回收时间(以毫秒为单位)
if (maxWait != null)
dataSource.setMaxWait(Long.parseLong(maxWait)); // 最大连接数
if (maxActive != null) {
if (!maxActive.trim().equals("0"))
dataSource.setMaxActive(Integer.parseInt(maxActive));
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("创建连接池失败!请检查设置!!!");
}
} /**
* 数据库连接
* @return
* @throws SQLException
*/
public static synchronized Connection getConnection() throws SQLException {
if (dataSource == null) {
init();
}
Connection conn = null;
if (dataSource != null) {
conn = dataSource.getConnection();
}
return conn;
} /**
* 关闭数据库
* @param conn
*/
public void closeConnection(Connection conn){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
System.out.println("关闭资源失败");
e.printStackTrace();
}
}
} }
重构db.properties文件,在该文件中添加创建数据库连接池所需的信息,包括初始化连接数、最大空闲连接数、大小空闲连接数、最大连接数量以及超时回收时间。该文件内容如下所示:
#Oracle
#jdbc.driverClassName=oracle.jdbc.OracleDriver
#jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
#jdbc.username=root
#jdbc.password=123456 #Mysql
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/csdn
jdbc.username=root
jdbc.password=123456 dataSource.initialSize=10
dataSource.maxIdle=20
dataSource.minIdle=5
dataSource.maxActive=50
dataSource.maxWait=1000
测试类testCase:
package com.daliu.test;
import java.sql.SQLException;
import org.junit.Test;
import com.daliu.jdbc.DBUtility;
public class testCase {
/**
* 测试是否连接
* @throws SQLException
*/
@Test
public void testgetConnection() throws SQLException{
DBUtility db=new DBUtility();
System.out.println(db.getConnection());
}
}
操作数据库EmpDAO类:
package com.daliu.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; public class EmpDAO {
public static void main(String[] args) {
EmpDAO dao = new EmpDAO();
dao.findAll();
} /**
* 查询数据库表中的所有信息
*/
public void findAll() { Connection con = null;
Statement stmt = null;
ResultSet rs = null; try {
//1.获得连接
con = DBUtility.getConnection();
//2.通过Connection的createStatement()方法获取数据库操作对象Statement。
stmt = con.createStatement();
//3.通过调用Statement对象的executeQuery方法来执行SQL语句。
rs = stmt
.executeQuery("select empno, ename, sal, hiredate from emp");
//4.ResultSet 对象没有下一行时返回 false,因此可以在 while 循环中使用它来迭代结果集
while (rs.next()) {
System.out.println(rs.getInt("empno") + ","
+ rs.getString("ename") + "," + ","
+ rs.getDouble("sal") + "," + rs.getDate("hiredate"));
} } catch (SQLException e) {
System.out.println("数据库访问异常!");
throw new RuntimeException(e);
} finally {
try { //5.在finally块中,依次关闭ResultSet对象、Statement对象以及Connection对象。
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (con != null) {
con.close();
}
} catch (SQLException e) {
System.out.println("释放资源时发生异常");
}
}
}
}
Mysql脚本:
create database csdn; use csdn; CREATE TABLE emp(
empno int(4),
ename VARCHAR(10),
job VARCHAR(9),
mgr int(4),
hiredate DATE,
sal double(7,2),
comm double(7,2),
deptno double(2,0)
); INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-2-20',1600,300,30);
INSERT INTO emp VALUES(7521,'WARD','SALESMAN',7698,'1981-2-22',1250,500,30);
INSERT INTO emp VALUES(7566,'JONES','MANAGER',7839,'1981-4-2',2975,NULL,20);
INSERT INTO emp VALUES(7654,'MARTIN','SALESMAN',7698,'1981-9-21',1250,1400,30);
INSERT INTO emp VALUES(7698,'BLAKE','MANAGER',7839,'1981-5-1',2850,NULL,30);
INSERT INTO emp VALUES(7782,'CLARK','MANAGER',7839,'1981-6-9',2450,NULL,10);
INSERT INTO emp VALUES(7788,'SCOTT','ANALYST',7566,'1987-4-19',3000,NULL,20);
INSERT INTO emp VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-9-8',1500,0,30);
INSERT INTO emp VALUES(7876,'ADAMS','CLERK',7788,'1987-5-27',1100,NULL,20);
INSERT INTO emp VALUES(7900,'JAMES','CLERK',7698,'1981-12-1',950,NULL,30);
INSERT INTO emp VALUES(7902,'FORD','ANALYST',7566,'1981-12-3',3000,NULL,20);
INSERT INTO emp VALUES(7934,'MILLER','CLERK',7782,'1982-1-23',1300,NULL,10); select * from emp;
转载请标明:http://www.cnblogs.com/liuhongfeng/p/4174661.html
JDBC实例--工具类升级,使用Apache DBCP连接池重构DBUtility,让连接数据库更有效,更安全的更多相关文章
- 初识apache DBCP连接池
连接案例: 首先:我们使用的是mysql数据库,所以要有一个mysql和java的JDBCjar包: 然后是DBCP中的两个jar包,DBCP使用的话,需要两个包: dbcp.jar和pool.jar ...
- 20160406javaweb JDBC 实例工具类
一.建立静态的数据库配置文件: config.properties driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/datab ...
- DBUtils工具类和DBCP连接池
今日内容介绍 1.DBUtils2.处理结果集的八种方式3.连接池4.连接池的用法1 PrepareStatement接口预编译SQL语句 1.1 预处理对象 * 使用PreparedStatemen ...
- 【JDBC】工具类的抽取
jdbc.properties属性文件 driverClass=com.mysql.jdbc.Driver url=jdbc:mysql:///jdbctest username=root passw ...
- 免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作简易流量爬虫
前言 我们之前的爬虫都是模拟成浏览器后直接爬取,并没有动态设置IP代理以及UserAgent标识,本文记录免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作 ...
- Java基础-DBCP连接池(BasicDataSource类)详解
Java基础-DBCP连接池(BasicDataSource类)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程 ...
- day39-Spring 14-Spring的JDBC模板:DBCP连接池配置
一般常用的连接池是DBCP和C3P0. package cn.itcast.spring3.demo1; import java.sql.DriverManager; import org.junit ...
- 21Spring_JdbcTemplatem模板工具类的使用——配置文件(连接三种数据库连接池)
上一篇文章提到过DriverManagerDataSource只是Spring内置的数据库连接池,我们可选的方案还有c3p0数据库连接池以及DBCP数据库连接池. 所以这篇文章讲一下上面三种数据库连接 ...
- JDBC连接池(三)DBCP连接池
JDBC连接池(三)DBCP连接池 在前面的随笔中提到 了 1.JDBC自定义连接池 2. C3P0连接池 今天将介绍DBCP连接池 第一步要导入jar包 (注意:mysql和mysql 驱动 ...
随机推荐
- Android中UI设计的一些技巧!!!
出处:http://blog.csdn.net/android_tutor/article/details/5995759 大家好,今天给大家分享的是Android中UI设计的一些技巧,本节内容主要有 ...
- codeforces 444 C. DZY Loves Colors(线段树)
题目大意: 1 l r x操作 讲 [l,r]上的节点涂成x颜色,而且每一个节点的值都加上 |y-x| y为涂之前的颜色 2 l r 操作,求出[l,r]上的和. 思路分析: 假设一个区间为同样的颜 ...
- Flask 学习(四)静态文件
Flask 学习(四)静态文件 动态 web 应用也需要静态文件,一般是 CSS 和 JavaScript 文件.理想情况下你的服务器已经配置好提供静态文件的服务. 在开发过程中, Flask 也能做 ...
- 字符串转换成JSON的三种方式
采用Ajax的项目开发过程中,经常需要将JSON格式的字符串返回到前端,前端解析成JS对象(JSON ).ECMA-262(E3) 中没有将JSON概念写到标准中,但在 ECMA-262(E5) 中J ...
- How To Open An URL In Android’s Web Browser
How To Open An URL In Android’s Web Browser 以下核心代码片断,将展现使用“android.content.Intent” 打开一个指定的 URL. butt ...
- pytorch hook使用
由于pytorch会自动舍弃图计算的中间结果,所以想要获取这些数值就需要使用钩子函数. 钩子函数包括Variable的钩子和nn.Module钩子,用法相似. import torch from to ...
- :Windows下RabbitMQ安装及入门
1.Windows下安装RabbitMQ需要以下几个步骤 (1):下载erlang,原因在于RabbitMQ服务端代码是使用并发式语言erlang编写的,下载地址:http://www.erlang. ...
- MySql的入侵测试以及防范
在做了之前的SQL SERVER之后,便很想尝试一下MYSQL的入侵测试已经防范,与大家一起分享. 总的来说,我一直在用的是MYSQL,对MYSQL比较熟悉,相比较而言,感觉MYSQL更安全,这只是我 ...
- qt creator修改程序编码(解决中文乱码问题)的方法
qt creator修改程序编码(解决中文乱码问题)的方法 qt creator修改程序编码的功能有几处. 1.edit - select encoding 选择载入(显示)编码和储存编码,其中GB2 ...
- (step4.1.2)hdu 1969(Pie——二分查找)
题目大意:n块馅饼分给m+1个人,每个人的馅饼必须是整块的,不能拼接,求最大的. 解题思路: 1)用总饼的体积除以总人数,得到每个人最大可以得到的V.但是每个人手中不能有两片或多片拼成的一块饼. 代码 ...