直接使用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,让连接数据库更有效,更安全的更多相关文章

  1. 初识apache DBCP连接池

    连接案例: 首先:我们使用的是mysql数据库,所以要有一个mysql和java的JDBCjar包: 然后是DBCP中的两个jar包,DBCP使用的话,需要两个包: dbcp.jar和pool.jar ...

  2. 20160406javaweb JDBC 实例工具类

    一.建立静态的数据库配置文件: config.properties driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/datab ...

  3. DBUtils工具类和DBCP连接池

    今日内容介绍 1.DBUtils2.处理结果集的八种方式3.连接池4.连接池的用法1 PrepareStatement接口预编译SQL语句 1.1 预处理对象 * 使用PreparedStatemen ...

  4. 【JDBC】工具类的抽取

    jdbc.properties属性文件 driverClass=com.mysql.jdbc.Driver url=jdbc:mysql:///jdbctest username=root passw ...

  5. 免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作简易流量爬虫

    前言 我们之前的爬虫都是模拟成浏览器后直接爬取,并没有动态设置IP代理以及UserAgent标识,本文记录免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作 ...

  6. Java基础-DBCP连接池(BasicDataSource类)详解

    Java基础-DBCP连接池(BasicDataSource类)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程 ...

  7. day39-Spring 14-Spring的JDBC模板:DBCP连接池配置

    一般常用的连接池是DBCP和C3P0. package cn.itcast.spring3.demo1; import java.sql.DriverManager; import org.junit ...

  8. 21Spring_JdbcTemplatem模板工具类的使用——配置文件(连接三种数据库连接池)

    上一篇文章提到过DriverManagerDataSource只是Spring内置的数据库连接池,我们可选的方案还有c3p0数据库连接池以及DBCP数据库连接池. 所以这篇文章讲一下上面三种数据库连接 ...

  9. JDBC连接池(三)DBCP连接池

    JDBC连接池(三)DBCP连接池 在前面的随笔中提到 了  1.JDBC自定义连接池  2. C3P0连接池 今天将介绍DBCP连接池 第一步要导入jar包   (注意:mysql和mysql 驱动 ...

随机推荐

  1. Android中UI设计的一些技巧!!!

    出处:http://blog.csdn.net/android_tutor/article/details/5995759 大家好,今天给大家分享的是Android中UI设计的一些技巧,本节内容主要有 ...

  2. codeforces 444 C. DZY Loves Colors(线段树)

    题目大意: 1 l r x操作 讲 [l,r]上的节点涂成x颜色,而且每一个节点的值都加上 |y-x| y为涂之前的颜色 2 l r  操作,求出[l,r]上的和. 思路分析: 假设一个区间为同样的颜 ...

  3. Flask 学习(四)静态文件

    Flask 学习(四)静态文件 动态 web 应用也需要静态文件,一般是 CSS 和 JavaScript 文件.理想情况下你的服务器已经配置好提供静态文件的服务. 在开发过程中, Flask 也能做 ...

  4. 字符串转换成JSON的三种方式

    采用Ajax的项目开发过程中,经常需要将JSON格式的字符串返回到前端,前端解析成JS对象(JSON ).ECMA-262(E3) 中没有将JSON概念写到标准中,但在 ECMA-262(E5) 中J ...

  5. 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 ...

  6. pytorch hook使用

    由于pytorch会自动舍弃图计算的中间结果,所以想要获取这些数值就需要使用钩子函数. 钩子函数包括Variable的钩子和nn.Module钩子,用法相似. import torch from to ...

  7. :Windows下RabbitMQ安装及入门

    1.Windows下安装RabbitMQ需要以下几个步骤 (1):下载erlang,原因在于RabbitMQ服务端代码是使用并发式语言erlang编写的,下载地址:http://www.erlang. ...

  8. MySql的入侵测试以及防范

    在做了之前的SQL SERVER之后,便很想尝试一下MYSQL的入侵测试已经防范,与大家一起分享. 总的来说,我一直在用的是MYSQL,对MYSQL比较熟悉,相比较而言,感觉MYSQL更安全,这只是我 ...

  9. qt creator修改程序编码(解决中文乱码问题)的方法

    qt creator修改程序编码(解决中文乱码问题)的方法 qt creator修改程序编码的功能有几处. 1.edit - select encoding 选择载入(显示)编码和储存编码,其中GB2 ...

  10. (step4.1.2)hdu 1969(Pie——二分查找)

    题目大意:n块馅饼分给m+1个人,每个人的馅饼必须是整块的,不能拼接,求最大的. 解题思路: 1)用总饼的体积除以总人数,得到每个人最大可以得到的V.但是每个人手中不能有两片或多片拼成的一块饼. 代码 ...