| @@ -7,7 +7,7 @@ | |||||
| * [主要步骤](#主要步骤) | * [主要步骤](#主要步骤) | ||||
| * [创建项目](#创建项目) | * [创建项目](#创建项目) | ||||
| * [引入依赖](#引入依赖) | * [引入依赖](#引入依赖) | ||||
| * [编写`dbcp.prperties`](#编写dbcpprperties) | |||||
| * [编写dbcp.prperties](#编写dbcpprperties) | |||||
| * [获取连接池和获取连接](#获取连接池和获取连接) | * [获取连接池和获取连接](#获取连接池和获取连接) | ||||
| * [编写测试类](#编写测试类) | * [编写测试类](#编写测试类) | ||||
| * [配置文件详解](#配置文件详解) | * [配置文件详解](#配置文件详解) | ||||
| @@ -50,7 +50,6 @@ | |||||
| # 简介 | # 简介 | ||||
| `DBCP`用于创建和管理连接,利用“池”的方式复用连接减少资源开销,和其他连接池一样,也具有连接数控制、连接有效性检测、连接泄露控制、缓存语句等功能。目前,`tomcat`自带的连接池就是`DBCP`,Spring开发组也推荐使用`DBCP`,阿里的`druid`也是参照`DBCP`开发出来的。 | `DBCP`用于创建和管理连接,利用“池”的方式复用连接减少资源开销,和其他连接池一样,也具有连接数控制、连接有效性检测、连接泄露控制、缓存语句等功能。目前,`tomcat`自带的连接池就是`DBCP`,Spring开发组也推荐使用`DBCP`,阿里的`druid`也是参照`DBCP`开发出来的。 | ||||
| @@ -130,7 +129,7 @@ | |||||
| </dependency> | </dependency> | ||||
| ``` | ``` | ||||
| ## 编写`dbcp.prperties` | |||||
| ## 编写dbcp.prperties | |||||
| 路径`resources`目录下,因为是入门例子,这里仅给出数据库连接参数和连接池基本参数,后面源码会对配置参数进行详细说明。另外,数据库`sql`脚本也在该目录下。 | 路径`resources`目录下,因为是入门例子,这里仅给出数据库连接参数和连接池基本参数,后面源码会对配置参数进行详细说明。另外,数据库`sql`脚本也在该目录下。 | ||||
| @@ -167,7 +166,7 @@ maxWaitMillis=-1 | |||||
| ## 获取连接池和获取连接 | ## 获取连接池和获取连接 | ||||
| 项目中编写了`JDBCUtils`来初始化连接池、获取连接、管理事务和释放资源等,具体参见项目源码。 | |||||
| 项目中编写了`JDBCUtils`来初始化连接池、获取连接和释放资源等,具体参见项目源码。 | |||||
| 路径:`cn.zzs.dbcp` | 路径:`cn.zzs.dbcp` | ||||
| ```java | ```java | ||||
| @@ -187,7 +186,7 @@ maxWaitMillis=-1 | |||||
| ```java | ```java | ||||
| @Test | @Test | ||||
| public void save() { | |||||
| public void save() throws SQLException { | |||||
| // 创建sql | // 创建sql | ||||
| String sql = "insert into demo_user values(null,?,?,?,?,?)"; | String sql = "insert into demo_user values(null,?,?,?,?,?)"; | ||||
| Connection connection = null; | Connection connection = null; | ||||
| @@ -196,7 +195,7 @@ maxWaitMillis=-1 | |||||
| // 获得连接 | // 获得连接 | ||||
| connection = JDBCUtils.getConnection(); | connection = JDBCUtils.getConnection(); | ||||
| // 开启事务设置非自动提交 | // 开启事务设置非自动提交 | ||||
| JDBCUtils.startTrasaction(); | |||||
| connection.setAutoCommit(false); | |||||
| // 获得Statement对象 | // 获得Statement对象 | ||||
| statement = connection.prepareStatement(sql); | statement = connection.prepareStatement(sql); | ||||
| // 设置参数 | // 设置参数 | ||||
| @@ -208,10 +207,7 @@ maxWaitMillis=-1 | |||||
| // 执行 | // 执行 | ||||
| statement.executeUpdate(); | statement.executeUpdate(); | ||||
| // 提交事务 | // 提交事务 | ||||
| JDBCUtils.commit(); | |||||
| } catch(Exception e) { | |||||
| JDBCUtils.rollback(); | |||||
| log.error("保存用户失败", e); | |||||
| connection.commit(); | |||||
| } finally { | } finally { | ||||
| // 释放资源 | // 释放资源 | ||||
| JDBCUtils.release(connection, statement, null); | JDBCUtils.release(connection, statement, null); | ||||
| @@ -463,7 +459,7 @@ accessToUnderlyingConnectionAllowed=false | |||||
| 研究之前,先来看下`BasicDataSource`的`UML`图: | 研究之前,先来看下`BasicDataSource`的`UML`图: | ||||
| <img src="https://img2018.cnblogs.com/blog/1731892/201912/1731892-20191228171436263-280030888.png" alt="BasicDataSource的UML图" style="zoom:100%;" /> | |||||
|  | |||||
| 这里介绍下这几个类的作用: | 这里介绍下这几个类的作用: | ||||
| @@ -517,7 +513,7 @@ accessToUnderlyingConnectionAllowed=false | |||||
| if(dataSource != null) { | if(dataSource != null) { | ||||
| return dataSource; | return dataSource; | ||||
| } | } | ||||
| // 注册MBean,用于支持JMX,这方面的内容不在这里扩展,相关内容可阅读我的另一篇博客:深入理解JMX | |||||
| // 注册MBean,用于支持JMX,这方面的内容不在这里扩展 | |||||
| jmxRegister(); | jmxRegister(); | ||||
| // 创建原生Connection工厂:本质就是持有数据库驱动对象和几个连接参数 | // 创建原生Connection工厂:本质就是持有数据库驱动对象和几个连接参数 | ||||
| @@ -553,8 +549,7 @@ accessToUnderlyingConnectionAllowed=false | |||||
| ``` | ``` | ||||
| 以上方法涉及到几个类,这里再补充下`UML`图。 | 以上方法涉及到几个类,这里再补充下`UML`图。 | ||||
| <img src="https://img2018.cnblogs.com/blog/1731892/201912/1731892-20191228171502877-1140170931.png" alt="GenericObjectPool的UML图" style="zoom:100%;" /> | |||||
|  | |||||
| | 类名 | 描述 | | | 类名 | 描述 | | ||||
| | --------------------------- | ------------------------------------------------------------ | | | --------------------------- | ------------------------------------------------------------ | | ||||
| @@ -566,7 +561,7 @@ accessToUnderlyingConnectionAllowed=false | |||||
| 上面已经大致分析了数据源和连接池对象的获取过程,接下来研究下连接对象的获取。在此之前先了解下`DBCP`中几个`Connection`实现类。 | 上面已经大致分析了数据源和连接池对象的获取过程,接下来研究下连接对象的获取。在此之前先了解下`DBCP`中几个`Connection`实现类。 | ||||
| <img src="https://img2018.cnblogs.com/blog/1731892/201912/1731892-20191228171525594-1114346897.png" alt="DelegatingConnection的UML图" style="zoom:100%;" /> | |||||
|  | |||||
| 类名|描述 | 类名|描述 | ||||
| -|- | -|- | ||||
| @@ -89,56 +89,6 @@ public class JDBCUtils { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * | |||||
| * <p>开启事务</p> | |||||
| * @author: zzs | |||||
| * @date: 2019年11月3日 上午11:03:24 | |||||
| * @return: void | |||||
| * @throws Exception | |||||
| */ | |||||
| public static void startTrasaction() throws SQLException { | |||||
| getConnection().setAutoCommit(false); | |||||
| } | |||||
| /** | |||||
| * | |||||
| * <p>提交事务</p> | |||||
| * @author: zzs | |||||
| * @date: 2019年11月3日 上午11:05:54 | |||||
| * @return: void | |||||
| */ | |||||
| public static void commit() { | |||||
| Connection connection = tl.get(); | |||||
| if(connection != null) { | |||||
| try { | |||||
| connection.commit(); | |||||
| connection.setAutoCommit(true); | |||||
| } catch(SQLException e) { | |||||
| log.error("提交事务失败", e); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * | |||||
| * <p>回滚事务</p> | |||||
| * @author: zzs | |||||
| * @date: 2019年11月3日 上午11:08:12 | |||||
| * @return: void | |||||
| */ | |||||
| public static void rollback() { | |||||
| Connection connection = tl.get(); | |||||
| if(connection != null) { | |||||
| try { | |||||
| connection.rollback(); | |||||
| connection.setAutoCommit(true); | |||||
| } catch(SQLException e) { | |||||
| log.error("回滚事务失败", e); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * | * | ||||
| * <p>创建数据库连接</p> | * <p>创建数据库连接</p> | ||||
| @@ -6,24 +6,21 @@ import java.sql.PreparedStatement; | |||||
| import java.sql.ResultSet; | import java.sql.ResultSet; | ||||
| import java.sql.SQLException; | import java.sql.SQLException; | ||||
| import org.apache.commons.logging.Log; | |||||
| import org.apache.commons.logging.LogFactory; | |||||
| import org.junit.Test; | import org.junit.Test; | ||||
| /** | /** | ||||
| * @Description: 测试使用BasicDataSource获取连接并操作数据库 | |||||
| * <p>测试使用BasicDataSource获取连接并操作数据库</p> | |||||
| * @author: zzs | * @author: zzs | ||||
| * @date: 2019年8月31日 下午9:39:54 | * @date: 2019年8月31日 下午9:39:54 | ||||
| */ | */ | ||||
| public class BasicDataSourceTest { | public class BasicDataSourceTest { | ||||
| private static final Log log = LogFactory.getLog(BasicDataSourceTest.class); | |||||
| /** | /** | ||||
| * 测试添加用户 | |||||
| * <p>测试添加用户</p> | |||||
| * @throws SQLException | |||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void save() { | |||||
| public void save() throws SQLException { | |||||
| // 创建sql | // 创建sql | ||||
| String sql = "insert into demo_user values(null,?,?,?,?,?)"; | String sql = "insert into demo_user values(null,?,?,?,?,?)"; | ||||
| Connection connection = null; | Connection connection = null; | ||||
| @@ -32,7 +29,7 @@ public class BasicDataSourceTest { | |||||
| // 获得连接 | // 获得连接 | ||||
| connection = JDBCUtils.getConnection(); | connection = JDBCUtils.getConnection(); | ||||
| // 开启事务设置非自动提交 | // 开启事务设置非自动提交 | ||||
| JDBCUtils.startTrasaction(); | |||||
| connection.setAutoCommit(false); | |||||
| // 获得Statement对象 | // 获得Statement对象 | ||||
| statement = connection.prepareStatement(sql); | statement = connection.prepareStatement(sql); | ||||
| // 设置参数 | // 设置参数 | ||||
| @@ -44,10 +41,7 @@ public class BasicDataSourceTest { | |||||
| // 执行 | // 执行 | ||||
| statement.executeUpdate(); | statement.executeUpdate(); | ||||
| // 提交事务 | // 提交事务 | ||||
| JDBCUtils.commit(); | |||||
| } catch(Exception e) { | |||||
| JDBCUtils.rollback(); | |||||
| log.error("保存用户失败", e); | |||||
| connection.commit(); | |||||
| } finally { | } finally { | ||||
| // 释放资源 | // 释放资源 | ||||
| JDBCUtils.release(connection, statement, null); | JDBCUtils.release(connection, statement, null); | ||||
| @@ -55,10 +49,11 @@ public class BasicDataSourceTest { | |||||
| } | } | ||||
| /** | /** | ||||
| * 测试更新用户 | |||||
| * <p>测试更新用户</p> | |||||
| * @throws SQLException | |||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void update() { | |||||
| public void update() throws SQLException { | |||||
| // 创建sql | // 创建sql | ||||
| String sql = "update demo_user set age = ?,gmt_modified = ? where name = ?"; | String sql = "update demo_user set age = ?,gmt_modified = ? where name = ?"; | ||||
| Connection connection = null; | Connection connection = null; | ||||
| @@ -67,7 +62,7 @@ public class BasicDataSourceTest { | |||||
| // 获得连接 | // 获得连接 | ||||
| connection = JDBCUtils.getConnection(); | connection = JDBCUtils.getConnection(); | ||||
| // 开启事务 | // 开启事务 | ||||
| JDBCUtils.startTrasaction(); | |||||
| connection.setAutoCommit(false); | |||||
| // 获得Statement对象 | // 获得Statement对象 | ||||
| statement = connection.prepareStatement(sql); | statement = connection.prepareStatement(sql); | ||||
| // 设置参数 | // 设置参数 | ||||
| @@ -77,10 +72,7 @@ public class BasicDataSourceTest { | |||||
| // 执行 | // 执行 | ||||
| statement.executeUpdate(); | statement.executeUpdate(); | ||||
| // 提交事务 | // 提交事务 | ||||
| JDBCUtils.commit(); | |||||
| } catch(Exception e) { | |||||
| log.error("异常导致操作回滚", e); | |||||
| JDBCUtils.rollback(); | |||||
| connection.commit(); | |||||
| } finally { | } finally { | ||||
| // 释放资源 | // 释放资源 | ||||
| JDBCUtils.release(connection, statement, null); | JDBCUtils.release(connection, statement, null); | ||||
| @@ -88,10 +80,11 @@ public class BasicDataSourceTest { | |||||
| } | } | ||||
| /** | /** | ||||
| * 测试查找用户 | |||||
| * <p>测试查找用户</p> | |||||
| * @throws SQLException | |||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void findAll() { | |||||
| public void findAll() throws SQLException { | |||||
| // 创建sql | // 创建sql | ||||
| String sql = "select * from demo_user where deleted = false"; | String sql = "select * from demo_user where deleted = false"; | ||||
| Connection connection = null; | Connection connection = null; | ||||
| @@ -110,8 +103,6 @@ public class BasicDataSourceTest { | |||||
| int age = resultSet.getInt(3); | int age = resultSet.getInt(3); | ||||
| System.out.println("用户名:" + name + ",年龄:" + age); | System.out.println("用户名:" + name + ",年龄:" + age); | ||||
| } | } | ||||
| } catch(SQLException e) { | |||||
| log.error("查询用户异常", e); | |||||
| } finally { | } finally { | ||||
| // 释放资源 | // 释放资源 | ||||
| JDBCUtils.release(connection, statement, resultSet); | JDBCUtils.release(connection, statement, resultSet); | ||||
| @@ -119,7 +110,7 @@ public class BasicDataSourceTest { | |||||
| } | } | ||||
| /** | /** | ||||
| * 测试删除用户 | |||||
| * <p>测试删除用户</p> | |||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void delete() throws Exception { | public void delete() throws Exception { | ||||
| @@ -131,7 +122,7 @@ public class BasicDataSourceTest { | |||||
| // 获得连接 | // 获得连接 | ||||
| connection = JDBCUtils.getConnection(); | connection = JDBCUtils.getConnection(); | ||||
| // 设置非自动提交 | // 设置非自动提交 | ||||
| JDBCUtils.startTrasaction(); | |||||
| connection.setAutoCommit(false); | |||||
| // 获得Statement对象 | // 获得Statement对象 | ||||
| statement = connection.prepareStatement(sql); | statement = connection.prepareStatement(sql); | ||||
| // 设置参数 | // 设置参数 | ||||
| @@ -139,10 +130,7 @@ public class BasicDataSourceTest { | |||||
| // 执行 | // 执行 | ||||
| statement.executeUpdate(); | statement.executeUpdate(); | ||||
| // 提交事务 | // 提交事务 | ||||
| JDBCUtils.commit(); | |||||
| } catch(Exception e) { | |||||
| log.error("异常导致操作回滚", e); | |||||
| JDBCUtils.rollback(); | |||||
| connection.commit(); | |||||
| } finally { | } finally { | ||||
| // 释放资源 | // 释放资源 | ||||
| JDBCUtils.release(connection, statement, null); | JDBCUtils.release(connection, statement, null); | ||||