在GitHub上找了download了一个学生成绩管理系统的javaweb项目作为学习借鉴使用。原作者用到了c3p0技术,于是我就去网上找了一些博客准备自己配一配。首先是配置问题。
我用的是mysql8.0,在配置上和8.0以下的有些区别。我将先后贴出两者的配置方法,然后总结区别所在。
本文介绍以下三点(全部读完费时大概半小时,大家可根据需要读)
1、什么是数据库连接池以及为什么用数据库连接池
2、怎么使用连接池
3、在使用c3p0时遇到的沙雕错误(使用一定要注意的点)
一般我们在项目中操作数据库时,都是每次需要操作数据库就建立一个连接,操作完成后释放连接。因为jdbc没有保持连接的能力,一旦超过一定时间没有使用(大约几百毫秒),连接就会被自动释放掉。而每次新建连接都需要140毫秒左右的时间,所以耗费时间比较多。若使用C3P0连接池来池化连接,随时取用,则平均每次取用只需要10-20毫秒。这在高并发随机访问数据库的时候对效率的提升有很大帮助。
这项技术能明显提高对数据库操作的性能。
数据库连接池只改变获取数据库连接的方式,mysql增删查改的操作不变。下面讲讲使用c3p0获取数据库连接的三步
1、导入必须的三个jar包
(怎么导请另行搜索) (以下版本为我测试可用的版本)
怎么下载到需要的jar包可看我的另一篇文章(/xyx 还没写,后面推出)
(1)c3p0-0.9.5.2 (c3p0的jar包)
(2)mysql-connector-java-8.0.11 (jdbc驱动包)
(3)mchange-commons-java-0.2.11 (缺少这个包会报错)
2、在src目录下新建一个xml文件 c3p0-config.xml
注意,必须是这个文件名(因为c3p0的代码实现中默认指定了读取该路径下的该名字的文件,使用其他路径或其他名字,都会出现找不到文件的错误)。
3、将c3p0-config.xml 的文件内容换成如下代码
mysql 8.0以下版本用这个
jdbc:mysql://localhost:3306/mydb
com.mysql.jdbc.Driver
root
mysql 8.0及以上用这个
root
hy981201
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/ssms?characterEncoding=UTF-8
其中,以下几个property为最基本的(必须在文件中写),其他的可不写(会采用默认配置)
对比8.0分界的两个不同的配置文件可知,改变主要在driverClass和jdbcUrl上,大家根据自己的mysql版本配置就行了
----------------------------------------------以下为基于c3p0编写的DBUtil工具类和测试--------------------------------------------
编写DBUtil类和某个测试类(这里我用UserDao类,实现对User对应表的增删查改)
DBUtil.java
package c3p0;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.PreparedStatement;
import java.sql.Connection;
public class DBUtil {
private static ComboPooledDataSource comboPooledDataSource = null;
// 数据库连接池初始化(只做一次)
static {
// 读取c3p0的xml配置文件创建数据源,c3p0的xml配置文件c3p0-config.xml必须放在src目录下
//默认会找 xml 中的 default-config 分支
comboPooledDataSource = new ComboPooledDataSource();
}
/**
* 从数据源中获取数据库的连接
* @return Connection
*/
public static Connection getConnection() {
try {
return comboPooledDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
System.out.println("连接异常");
return null;
}
}
/**
* 释放资源,将数据库连接还给数据库连接池
* @param conn
* @param ps
* @param rs
*/
public static void closeDB(ResultSet rs, PreparedStatement ps,Connection conn) {
try {
if (rs != null) {
rs.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (ps != null) {
ps.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void closeDB(PreparedStatement ps, Connection conn) {
try {
if (ps != null) {
ps.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void closeDB(Connection conn) {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
UserDao.java(建议自己编写)
package dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import util.DBUtil;
public class UserDao {
public static void main(String[] args) {
String id = "201750080317";
String pwd = "981201";
// new UserDao().add(id,pwd);
// new UserDao().modify(id, pwd);
new UserDao().remove(id);
// new UserDao().find(id);
System.out.println("操作成功");
}
/**
* 在数据库中加入一个记录
* @param id
* @param pwd
* @throws SQLException
*/
public void add(String id,String pwd){
//数据库连接
Connection conn = DBUtil.getConnection();
// System.out.println("debug3");
//准备要执行的sql语句
String sql = "INSERT INTO `成员口令` (`账号`, `成员密码`) VALUES (?,?)";
//获取sql语句的执行器对象
PreparedStatement pstm;
try {
pstm = conn.prepareStatement(sql);
//设置参数
pstm.setString(1, id);
pstm.setString(2, pwd);
//执行sql语句
pstm.executeUpdate();
//释放
DBUtil.closeDB(pstm,conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void modify(String id,String pwd){
//数据库连接
Connection conn = DBUtil.getConnection();
//准备要执行的sql语句
String sql = "UPDATE `成员口令` SET `成员密码`=? WHERE (`账号`=?)";
//获取sql语句的执行器对象
PreparedStatement pstm;
try {
pstm = conn.prepareStatement(sql);
//设置参数
pstm.setString(1, pwd);
pstm.setString(2, id);
//执行sql语句
pstm.executeUpdate();
//释放
DBUtil.closeDB(pstm,conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void remove(String id){
//数据库连接
Connection conn = DBUtil.getConnection();
//准备要执行的sql语句
String sql = "DELETE FROM `成员口令` WHERE (`账号`=?)";
//获取sql语句的执行器对象
PreparedStatement pstm;
try {
pstm = conn.prepareStatement(sql);
//设置参数
pstm.setString(1, id);
//执行sql语句
pstm.executeUpdate();
//释放
DBUtil.closeDB(pstm,conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
public List find(String id){
List pwds = new LinkedList();
//数据库连接
Connection conn = DBUtil.getConnection();
//准备要执行的sql语句
//一定注意sql语句不要出一点点错
String sql = "SELECT * FROM `成员口令` WHERE (`账号` = ?)";
//获取sql语句的执行器对象
PreparedStatement pstm;
try {
String t;
pstm = conn.prepareStatement(sql);
pstm.setString(1, id);
ResultSet rs = pstm.executeQuery();
while(rs.next()){
t = rs.getString(2);
System.out.println(t);
pwds.add(t);
}
} catch (SQLException e) {
e.printStackTrace();
}
return pwds;
}
}
User对应的表
--------------------------------------------------工具类和测试结束--------------------------------------------------------------------------------
1、c3p0-config.xml文件一定放在src根目录下,否则会找不到
2、c3p0-config.xml中,字母该小写的一定小写,c3p0的’0‘是数字0,不是字母O,不按这个名字写会找不到
3、c3p0-config.xml中的配置文件一定不能有一点点的错误,否则数据库连接会出现异常
(我在配置的时候就把driver打成了drive,再加上我错误的着错误方法,在正确拼写这个问题上卡了一天)
同时,推荐一种弱智查错方式:以前c语言老师告诉我debug从最上面的error找起,从今天起,我将告诉我自己,debug从最上面的warn找起,一个warn可能就会使项目异常,然后整个项目跑不起来。
4、在一天的debug途中,有文章提到上面导入的jar包版本不对,出现找不到驱动的错误。我推荐的三个版本的jar包经过我的测试,没有问题,如果是出现找不到的jar包的错误,可以尝试换成我推荐的版本的jar包试试。