当前位置: 首页 > 编程日记 > 正文

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:

  1 package com.daliu.jdbc;
  2 
  3 import java.io.IOException;
  4 import java.sql.Connection;
  5 import java.sql.SQLException;
  6 import java.util.Properties;
  7 
  8 import org.apache.commons.dbcp.BasicDataSource;
  9 /**
 10  * 工具类
 11  * @author daliu_it
 12  *
 13  */
 14 public class DBUtility {
 15     private static BasicDataSource dataSource = null;
 16 
 17     public DBUtility() {
 18     }
 19     public static void init() {
 20 
 21         Properties dbProps = new Properties();
 22         // 取配置文件可以根据实际的不同修改
 23         try {
 24             dbProps.load(DBUtility.class.getClassLoader().getResourceAsStream(
 25                     "com/daliu/jdbc/db.properties"));
 26         } catch (IOException e) {
 27             e.printStackTrace();
 28         }
 29 
 30         try {
 31             String driveClassName = dbProps.getProperty("jdbc.driverClassName");
 32             String url = dbProps.getProperty("jdbc.url");
 33             String username = dbProps.getProperty("jdbc.username");
 34             String password = dbProps.getProperty("jdbc.password");
 35 
 36             String initialSize = dbProps.getProperty("dataSource.initialSize");
 37             String minIdle = dbProps.getProperty("dataSource.minIdle");
 38             String maxIdle = dbProps.getProperty("dataSource.maxIdle");
 39             String maxWait = dbProps.getProperty("dataSource.maxWait");
 40             String maxActive = dbProps.getProperty("dataSource.maxActive");
 41 
 42             dataSource = new BasicDataSource();
 43             dataSource.setDriverClassName(driveClassName);
 44             dataSource.setUrl(url);
 45             dataSource.setUsername(username);
 46             dataSource.setPassword(password);
 47 
 48             // 初始化连接数
 49             if (initialSize != null)
 50                 dataSource.setInitialSize(Integer.parseInt(initialSize));
 51 
 52             // 最小空闲连接
 53             if (minIdle != null)
 54                 dataSource.setMinIdle(Integer.parseInt(minIdle));
 55 
 56             // 最大空闲连接
 57             if (maxIdle != null)
 58                 dataSource.setMaxIdle(Integer.parseInt(maxIdle));
 59 
 60             // 超时回收时间(以毫秒为单位)
 61             if (maxWait != null)
 62                 dataSource.setMaxWait(Long.parseLong(maxWait));
 63 
 64             // 最大连接数
 65             if (maxActive != null) {
 66                 if (!maxActive.trim().equals("0"))
 67                     dataSource.setMaxActive(Integer.parseInt(maxActive));
 68             }
 69         } catch (Exception e) {
 70             e.printStackTrace();
 71             System.out.println("创建连接池失败!请检查设置!!!");
 72         }
 73     }
 74 
 75     /**
 76      * 数据库连接
 77      * @return
 78      * @throws SQLException
 79      */
 80     public static synchronized Connection getConnection() throws SQLException {
 81         if (dataSource == null) {
 82             init();
 83         }
 84         Connection conn = null;
 85         if (dataSource != null) {
 86             conn = dataSource.getConnection();
 87         }
 88         return conn;
 89     }
 90     
 91     /**
 92      * 关闭数据库
 93      * @param conn
 94      */
 95     public void closeConnection(Connection conn){
 96         if(conn!=null){
 97             try {
 98                 conn.close();
 99             } catch (SQLException e) {
100                 System.out.println("关闭资源失败");
101                 e.printStackTrace();
102             }
103         }
104     }
105     
106 }

重构db.properties文件,在该文件中添加创建数据库连接池所需的信息,包括初始化连接数、最大空闲连接数、大小空闲连接数、最大连接数量以及超时回收时间。该文件内容如下所示:

 1 #Oracle
 2 #jdbc.driverClassName=oracle.jdbc.OracleDriver
 3 #jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
 4 #jdbc.username=root
 5 #jdbc.password=123456
 6 
 7 #Mysql
 8 jdbc.driverClassName=com.mysql.jdbc.Driver
 9 jdbc.url=jdbc:mysql://localhost:3306/csdn
10 jdbc.username=root
11 jdbc.password=123456
12 
13 dataSource.initialSize=10
14 dataSource.maxIdle=20
15 dataSource.minIdle=5
16 dataSource.maxActive=50
17 dataSource.maxWait=1000

测试类testCase:

 1 package com.daliu.test;
 2 
 3 import java.sql.SQLException;
 4 
 5 import org.junit.Test;
 6 
 7 import com.daliu.jdbc.DBUtility;
 8 
 9 
10 public class testCase {
11 
12     /**
13      * 测试是否连接
14      * @throws SQLException
15      */
16     @Test
17     public void testgetConnection() throws SQLException{
18         DBUtility db=new DBUtility();
19         System.out.println(db.getConnection());
20     }
21 }

操作数据库EmpDAO类:

 1 package com.daliu.jdbc;
 2 import java.sql.Connection;
 3 import java.sql.ResultSet;
 4 import java.sql.SQLException;
 5 import java.sql.Statement;
 6 
 7 public class EmpDAO {
 8     public static void main(String[] args) {
 9         EmpDAO dao = new EmpDAO();
10         dao.findAll();
11     }
12 
13    /**
14     * 查询数据库表中的所有信息
15     */
16     public void findAll() {
17         
18         Connection con = null;
19         Statement stmt = null;
20         ResultSet rs = null;
21 
22         
23         try {
24             //1.获得连接
25             con = DBUtility.getConnection();
26             //2.通过Connection的createStatement()方法获取数据库操作对象Statement。
27             stmt = con.createStatement();
28             //3.通过调用Statement对象的executeQuery方法来执行SQL语句。
29             rs = stmt
30                     .executeQuery("select empno, ename, sal, hiredate from emp");
31             //4.ResultSet 对象没有下一行时返回 false,因此可以在 while 循环中使用它来迭代结果集
32             while (rs.next()) {
33                 System.out.println(rs.getInt("empno") + ","
34                         + rs.getString("ename") + "," + ","
35                         + rs.getDouble("sal") + "," + rs.getDate("hiredate"));
36             }
37             
38             
39         } catch (SQLException e) {
40             System.out.println("数据库访问异常!");
41             throw new RuntimeException(e);
42         } finally {
43             try {
44                 
45                 //5.在finally块中,依次关闭ResultSet对象、Statement对象以及Connection对象。
46                 if (rs != null) {
47                     rs.close();
48                 }
49                 if (stmt != null) {
50                     stmt.close();
51                 }
52                 if (con != null) {
53                     con.close();
54                 }
55             } catch (SQLException e) {
56                 System.out.println("释放资源时发生异常");
57             }
58         }
59     }
60 }

Mysql脚本:

 1 create database csdn;
 2 
 3 use csdn;
 4 
 5 CREATE TABLE emp(
 6     empno int(4),
 7     ename VARCHAR(10),
 8     job VARCHAR(9),
 9     mgr int(4),
10     hiredate DATE,
11     sal double(7,2),
12     comm double(7,2),
13     deptno double(2,0)
14 );
15 
16 INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
17 INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-2-20',1600,300,30);
18 INSERT INTO emp VALUES(7521,'WARD','SALESMAN',7698,'1981-2-22',1250,500,30);
19 INSERT INTO emp VALUES(7566,'JONES','MANAGER',7839,'1981-4-2',2975,NULL,20);
20 INSERT INTO emp VALUES(7654,'MARTIN','SALESMAN',7698,'1981-9-21',1250,1400,30);
21 INSERT INTO emp VALUES(7698,'BLAKE','MANAGER',7839,'1981-5-1',2850,NULL,30);
22 INSERT INTO emp VALUES(7782,'CLARK','MANAGER',7839,'1981-6-9',2450,NULL,10);
23 INSERT INTO emp VALUES(7788,'SCOTT','ANALYST',7566,'1987-4-19',3000,NULL,20);
24 INSERT INTO emp VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
25 INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-9-8',1500,0,30);
26 INSERT INTO emp VALUES(7876,'ADAMS','CLERK',7788,'1987-5-27',1100,NULL,20);
27 INSERT INTO emp VALUES(7900,'JAMES','CLERK',7698,'1981-12-1',950,NULL,30);
28 INSERT INTO emp VALUES(7902,'FORD','ANALYST',7566,'1981-12-3',3000,NULL,20);
29 INSERT INTO emp VALUES(7934,'MILLER','CLERK',7782,'1982-1-23',1300,NULL,10);
30 
31 select * from emp;

转载请标明:http://www.cnblogs.com/liuhongfeng/p/4174661.html

相关文章:

程序员的自我修养--链接、装载与库笔记:Linux共享库的组织

共享库(Shared Library)概念:其实从文件结构上来讲,共享库和共享对象没什么区别,Linux下的共享库就是普通的ELF共享对象。由于共享对象可以被各个程序之间共享,所以它也就成为了库的很好的存在形式,很多库的开发者都以…

iOS下JS与原生OC互相调用

iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式。 JS调用原生OC篇 方式一 第一种方式是用JS发起一个假的URL请求,然后利用UIWebView的代理方法拦截这次请求,然后再做相…

马斯克发首款会上火星的电动皮卡:28万起,可防弹,造型相当“赛博朋克”...

整理 | Jane、非主流出品 | AI科技大本营(ID:rgznai100)【导读】马斯克今日发布酝酿多年、“真爱系列”的第一辆电动皮卡Cybertruck,Cybertruck 是赛博朋克(cyberpunk)与卡车(truck)…

让你提升命令行效率的 Bash 快捷键

为什么80%的码农都做不了架构师?>>> 原文:http://linuxtoy.org/archives/bash-shortcuts.html 生活在 Bash shell 中,熟记以下快捷键,将极大的提高你的命令行操作效率。 编辑命令 Ctrl a :移到命令行首Ct…

程序员的自我修养--链接、装载与库笔记:Windows下的动态链接

Windows下的PE的动态链接与Linux下的ELF动态链接相比,有很多类似的地方,但也有很多不同的地方。 1. DLL简介 DLL即动态链接库(Dynamic-Link Library)的缩写,它相当于Linux下的共享对象。Windows系统中大量采用了这种DLL机制,甚至…

iOS下JS与OC互相调用(一)--UIWebView 拦截URL

1.在JS 中做一次URL跳转,然后在OC中拦截跳转。(这里分为UIWebView 和 WKWebView两种,去年因为还要兼容iOS 6,所以没办法只能采用UIWebView来做。)2.利用WKWebView 的MessageHandler。3.利用系统库JavaScriptCore&#…

AI换脸鉴别率超99.6%,微软用技术应对虚假信息

来源 | 微软亚洲研究院AI头条(ID:MSRAsia)近日社交网络上爆红的一款换脸应用,让许多普通用户体验到了跟爱豆同框、与偶像飙戏的快乐,也因数据使用带来的问题陷入了舆论的漩涡——除了用户隐私保障,如何辨别和处理换脸应…

使用Apache Tiles3.x构建界面布局(一)

Tiles是一个免费的开源模板Java应用程序的框架。基于复合模式简化的用户界面的构建。对于复杂的网站仍是最简单、最优雅的方式与任何MVC技术一起工作。Struts2对Tiles提供了支持,如今Tiles发展已有13个年头,成为Apache的一个独立项目,我们可以…

iOS下JS与OC互相调用(二)--WKWebView 拦截URL

在上篇文章中讲述了使用UIWebView拦截URL的方式来处理JS与OC交互。 由于UIWebView比较耗内存,性能上不太好,而苹果在iOS 8中推出了WKWebView。 同样的用WKWebView也可以拦截URL,做JS 与OC交互。关于WKWebView与UIWebView的对比,大…

基于模型的强化学习比无模型的强化学习更好?错!

作者 | Carles Gelada and Jacob Buckman编辑 | DeepRL来源 | 深度强化学习实验室(ID:Deep-RL)【导读】许多研究人员认为,基于模型的强化学习(MBRL)比无模型的强化学习(MFRL)具有更高的样本效率。但是&…

程序员的自我修养--链接、装载与库笔记:内存

1. 程序的内存布局 现代的应用程序都运行在一个内存空间里,在32位的系统里,这个内存空间拥有4GB(2的32次方)的寻址能力。应用程序可以直接使用32位的地址进行寻址,这被称为平坦(flat)的内存模型。在平坦的内存模型中,整个内存是一…

【Away3D代码解读】(四):主要模块简介

数据模块: Away3D中最核心的数据类是Mesh类,我们先看看Mesh类的继承关系: NamedAssetBase:为对象提供id和name属性,是Away3D大部分类的基类; Object3D:3D对象基类,提供方便操作3D对象…

程序员的自我修养--链接、装载与库笔记:运行库

1. 入口函数和程序初始化 程序从main开始吗?:操作系统装载程序之后,首先运行的代码并不是main的第一行,而是某些别的代码,这些代码负责准备好main函数执行所需要的环境,并且负责调用main函数,这…

iOS下JS与OC互相调用(三)--MessageHandler

使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式。那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法。 MessageHandler 是什么? WKWebView 初始化时,有一个参数叫…

北大教授张大庆:无线感知,让你变老也优雅

受访者 | 张大庆记者 | 胡巍巍出品 | CSDN(ID:CSDNnews)在国内高校中,北大的校庆日很特殊——5月4日。这一天,也是青年节。北大,是五四运动的策源地。100年来,“爱国、进步、民主、科学”的五四…

总结 20 个开发细节

2019独角兽企业重金招聘Python工程师标准>>> 1:提交到SVN的代码必须有提交备注,以便于以后查看。 2:如考虑页面缓存,可以在路径后增加随机数:url "&TimeS" Math.random();。 3:…

程序员的自我修养--链接、装载与库笔记:系统调用与API

系统调用(System Call)是应用程序(运行库也是应用程序的一部分)与操作系统内核之间的接口,它决定了应用程序是如何与内核打交道的。无论程序是直接进行系统调用,还是通过运行库,最终还是会到达系统调用这个层面上。 1. 系统调用介绍 什么是…

iOS下JS与OC互相调用(四)--JavaScriptCore

前面讲完拦截URL的方式实现JS与OC互相调用,终于到JavaScriptCore了。它是从iOS7开始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封装了一下,提供了简单快捷的方式与JavaScript交互。 关于JavaScriptCore的使用有两篇很好的文章&…

围巾都这么黑科技了,是我见识少了

有一个永恒的话题:北方冷一点还是南方冷一点?答案是:哪里都冷!冬天最痛苦的莫过于走出空调房——刺骨的风直直的从领口处灌进去那叫一个“透心凉,心飞扬”缠了好几圈的大围巾却根本没什么保暖效果每当这时候&#xff0…

【教程】【FLEX】#004 反射机制

总结: 目前用到反射的主要有两个方法 1. getDefinitionByName //根据类名,返回对象(反射实例化对象) 2. describeType //根据对象,返回XML格式的属性,方法等信息(反射得到…

iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge

WebViewJavascriptBridge是一个有点年代的JS与OC交互的库,使用该库的著名应用还挺多的,目前这个库有7000star。我去翻看了它的第一版本已经是4年前了,在版本V4.1.4以及之前,该库只有一个类和一个js 的txt文件,所以旧版…

OpenCV代码提取:Windows上通过DShow获取Camera视频

在OpenCV 3.1中获取视频的模块在videoio(video input and output module)中,调用VideoCapture类接口,除了videoio模块外还依赖core、highgui、imgproc、imgcodecs四个模块,而OpenCV 2.4.13.6仅需要core、highgui、imgproc三个模块。3.1中的vi…

迁移学习与图神经网络“合力”模型:用DoT-GNN克服组重识别难题

作者 | Ziling Huang、Zheng Wang、Wei Hu、Chia-Wen Lin、Shin’ichi Satoh译者 | 刘畅编辑 | Jane出品 | AI科技大本营(ID:rgznai100)【导读】目前,大多数行人重识别(ReID)方法主要是从收集的单个人图像数…

struts2 select 默认选中

jsp:<s:select list"#{1:男,2:女}" name"sex"/> action:private String sex;sex属性有get/set方法。在业务方法中设置sex "2";select会默认选中。

通过Windows DShow获取设备名、支持的编解码及视频size列表实现

之前在https://blog.csdn.net/fengbingchun/article/details/102641967中介绍过通过DShow获取Camera视频的实现&#xff0c;即调用VideoCapture类。在OpenCV的VideoCapture类中并没有提供获取Camera设备列表、支持的编解码类型列表及支持的video size列表接口&#xff0c;这里基…

15篇论文全面概览BERT压缩方法

作者 | Mitchell A. Gordon译者 | 孙薇出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;模型压缩可减少受训神经网络的冗余——由于几乎没有BERT或者BERT-Large模型可用于GPU及智能手机上&#xff0c;这一点就非常有用了。另外&#xff0c;内存与推理速度的提高也能节…

iOS下JS与OC互相调用(七)--Cordova 基础

Cordova 简介 在介绍Cordova之前&#xff0c;必须先提一下PhoneGap。PhoneGap 是Nitobi软件公司2008年推出的一个框架&#xff0c;旨在弥补web 和iOS 之间的不足&#xff0c;使得web 和 iPhone SDK 之间的交互更容易。后来又加入了Android SDK 和BlackBerry SDK&#xff0c;再然…

在linux上MySQL的三种安装方式

安装MySQL的方式常见的有三种&#xff1a;方式一&#xff1a;rpm安装(1) 操作系统发行商提供的(2) MySQL官方提供的&#xff08;版本更新&#xff0c;修复了更多常见BUG&#xff09;www.mysql.com/downloads关于MySQL中rpm包类型的介绍&#xff1a;MySQL-client 客户端…

通过libjpeg-turbo实现对jpeg图像的解码

之前在https://blog.csdn.net/fengbingchun/article/details/89715416中介绍过通过libjpeg-turbo接口实现将数据编码或压缩成jpeg数据并通过FILE的fwrite接口将其直接保存成*.jpg图像&#xff0c;当时用的是libjpeg的接口&#xff0c;其实还可以使用turbojpeg api的接口即tjCom…

AI+大数据顶级技术盛会开幕在即,6.6折特惠票限时抢购

2019年12月5-7日&#xff0c;由中国计算机学会主办&#xff0c;CCF 大数据专家委员会承办&#xff0c;CSDN、中科天玑数据科技股份有限公司协办的中国大数据技术大会&#xff08;BDTC 2019&#xff09;将于北京长城饭店隆重举行。届时&#xff0c;超过百位顶尖技术专家将齐聚于…