文章目录
前言
在许多 Web 应用中,服务需需要和用户进行必要的数据交互。例如,服务需需要将用户提供的数据永久安全地保存在服务需端,需要为用户提供数据查询等,此时, Web 应用就可能需要和数据库打交道,其原因是数据库在数据查询.修改.保存.安全等方面有着其他数据处理手段无法蔡代的地位。许多优秀的数据库管理系统在数据管理,特别是在基于 Web 的数据管理方面在扮演着重要的角色 。
8.1、MySQL数据库管理系统
MySQL 数据库管理系统,简称 MySQL ,是目前流行的开源数据库管理系统,其社区版(MySQL Community Edition)是可免费下载的开源数据库管理系统。MySQL 最初由瑞典MySQL AB 公司开发,目前由 Oracle 公司负责源代码的维护和升级。Oracle 将 MySQL 分为社区版和商业版,并保留 MySQL 开放源码这一特点。目前许多 Web 开发项目都选用社区版MySQL ,其主要原因是社区版 MySQL 的性能晶越 ,满足许多 Web 应用已经绰绰有余,而且社区版 MySQL 是开源数据库管理系统,可以降低软件的开发和使用成本 。
请大家自行搜索如何下载MySQL数据库,在这里不再赘述
8.2、连接MySQL数据库
为了使 Java 编写的程序不依赖于具体的数据库 ,Java 提供了专门用于操作数据库的 API,即 JDBC(Java DataBase Connectivity)。JDBC 操作不同的数据库时,仅仅是加载的数据库连接需不同以及和数据库建立连接的方式不同而已。使用JDBC 的应用程序和数据库建立连接之后,就可以使用JDBC 提供的 API 操作数
据库(如图 8.14 所示) 。
8.2.1、下载JDBC-MySQL数据库连接器
应用程序为了能访问 MySQL 数据库服务需上的数据库,必须要保证应用程序所驻留的计算机上安装有相应JDBC-MySQL 数据库连接器。直接在浏览器的地址栏中直接输入:https://dev. mysql. comy/downloads/Vconnector/j/。然后在给出的下拉列表 Select OperatingSystem 中选择 Platform Independent (即 Java 平台),然后选择 Platform Independent(Architecture Independent),ZIP 格式,单击 download 下载按钮即可。本书下载的是 mysqL-connector-java-8. 0. 18. zip(Linux 系统可下载 tar. gz 格式文件) ,将该 zip 文件解压至硬盘,在解压目录下的 mysql-connector-java-8. 0. 18. jar 文件就是连接 MySQL 数据库的JDBC-MySQL 数据库连接器(作者也将该文件放在了教学资源的源代码文件夹中) 。
将 MySQL 数据库的JDBC-MySQL 数据库连接需 mysql-connector-java-8. 0. 18. jar 保存到 Tomcat 安装目录下的1lib 文件夹中(例如 D:\apache-tomcat-9. 0. 26\lib) ,并重新启动Tomcat 服务需。
8.2.2、加载JDBC-MySQL数据库连接器
应用程序负责加载的JDBC-MySQL 连接需,代码如下(注意字符序列和 8. 0 版本之前的com. mysql. jdbc. Driver 不同) :
try{ Class. forName("com.mysql.cj. jdbc.Driver "”) ;
}
catch(Exception e){}
MySQL 数据库驱动是 mysql-connector-java-8. 0. 18. jar 文件中的 Driver 类 ,该类的包名是 com. mysql. cj. jdbc. Driver(包名和以前的版本不同) 。Driver 类不是 Java 运行环境类库中的类 ,是连接需 mysql-connector-java-8. 0. 18. jar 中的类 。
注: 不要忘记将 mysql-connector-java-8. 0. 18. jar 保存到 Tomcat 安装目录下的lib 文件夹中,并重新启动 Tomcat 服务器。
8.2.3、连接数据库
java. sqdl 包中的 DriverManager 突有网个用于建立连接的突方法(static 方法):
(1) Connection getConnection
(java. lang. String,java. lang. String,java. lang. String)
(2) Connection getConnection( java. lang. String)
上述两个方法都可能抛出 SQLException 异常,DriverManager 类调用上述方法可以和数据库建立连接,即可返回一个 Connection 对象。
为了能和 MySQL 数据库服务器管理的数据库建立连接,必须保证该 MySQL 数据库服务需已经启动,如果没有更改过 MySQL 数据库服务需的配置,那么该数据库服务吉占用的端口是 3306 。假设 MySQL 数据库服务咒所驻留的计算机的 IP 地址是 192. 168. 100. 1 (命令行运行 ipconfig 可以得到当前计算机的IP 地址) 。
应用程序要和 MySQL 数据库服务需管理的数据库 Book(在 8. 1. 3 节建立的数据库)建立连接,而有权访问数据库 Book 的用户的id 和密码分别是 root 和空。建立连接的代码如下 :
Connection con;
Stringurl =
“jdbc:mysql://192.168.100.1:3306/Book?useSSL = false&serverTimezone = GMT” ;
String user = “root”;
String password = " ";
try{
con = DriverManager. getConnection(url,user, password ) ; //连接代码
}
catch( SQLException e){
System. out. Println(e) ;
}
对于 MySQL 8. 0 版本 ,必须设置 serverTimezone 参数的值(值可以是 MySQL 8.0 支持的时区之一即可,例如 EST、CST、GMT 等) ,例如: serverTimezone王CST 或 serverTimezone一GMT(CCST 是 Eastern Standard Time 的缩写,CST 是 China Standard Time 的缩写,GMT 是Greenwich Mean Tim 缩写) 。如果 root 用户密码是 99 ,将 password=""更改为 password="99"即可。
MySQL 5.7 以及之后的版本建议应用程序和数据库服务器建立连接时明确设置 SSL(Secure Sockets Layer) ,即在连接信息里明确使用 useSSL 参数,并设置值是 true 或 false, 如果不设置 useSSL 参数 ,程序运行时总会提示用户程序进行明确设置(但不影响程序的运行)。对于早期的 MySQL 版本,用户程序不必设置该项。
应用程序和某个数据库建立连接之后,就可以通过 SQL 语句和该数据库中的表交互信息 ,比如查询.修改.更新表中的记录。
8.3、查询记录
和数据库建立连接后,就可以使用JDBC 提供的 API 与数据库交互信息,例如查询、修改和更新数据库中的表等。JDBC 与数据库表进行交互的主要方式是使用 SQL 语句(其他方式见8.5节)。JDBC 提供的 API 可以将标准的 SQL 语句发送给数据库 ,实现和数据库的交互。
8.3.1、结果集与查询
对一个数据库中的表进行查询,然后将查询结果返回到一个 ResultSet 对象中 ,习惯称 ResultSet 对象为结果集对象 。
使用 Statement 声明一个 SQL 语句对象 ,然后让已创建的连接对象 con 调用方法 createStatement()返回 SQL 语句对象 ,代码如下 :
try{ , Statement sql = con. createStatement( ) ;
}
catch(SQOLException e ){
System. out. println(e) ;
}
有了SQL 语句对象后,这个对象就可以调用相应的方法查询数据库中的表,并将查询结果存放在一个 ResultSet 结果集中。也就是说 SQL 查询语句对数据库的查询操作将返回一个ResultSet 结果集 ,ResultSset 结果集由以列(也称字段)为结构的数据行组成。例如 ,对于
ResultSet rs = sql. execute0Ouery(“SELECT x* FROMbookList’” ) ;
内存中的结果集对象 rs 的列数是4列,刚好和 bookList 表的列数相同 ,第 1 列至第 4 列分别是 ISBN ,name price 和 publishDate 列; 而对于
ResultSet rs = sql. execute0Query(“SELECT name, price FROMbookList””) ;
结果集对象 rs 只有两列,第 1 列是name列,第2列是price 列。
ResultSset 结果集一次只能看到一个数据行,使用 next()方法可走到下一数据行。获得一行数据后,ResultSet 结果集可以使用 getXxx -方法获得字段值(列值) ,将位置索引(第一列使用1 ,第二列使用 2 等)或列名传递给 getXxx 方法的参数即可。表 8. 1 给出了 Resultset 结果集的右干方法。
8.3.2、随机查询
有时候要在结果集中前后移动.显示结果集指定的一条(一行)记录或随机显示若干条记录等。这时,必须返回一个可滚动的结果集(结果集的游标可以上下移动)。为了得到一个可滚动的结果集,须使用下述方法先获得一个Statement 对象 ;
Statement stmt = Con. CreateStatement( int type int concurrencVYy) ;
然后 ,根据参数的 type、concurrency 的取值情况 ,stmt 返回相应类型的结果集 :
ResultSet re = stmt. execute0Ouery(SQL 语句 ) ;
(1) type 的取值决定滚动方式,取值可以是:
★ ResultSset.TYPE_ FORWORD ONLY: 结果集的游标只能向下滚动。
★ResultSet.TYPE SCROLL INSENSITIVE: 结果集的游标可以上下移动,当数据库变化时,当前结果集不变。
★ResultSset. TYPE_SCROLL_ SENSITIVE: 结果集的游标可以上下移动,当数据库变化时,当前结果集同步改变。
(2) Concurrency 取值决定是否可以用结果集更新数据库 ,Concurrency 取值 :
★ ResultSet. CONCUR_READ_ONLY: 不能用结果集更新数据库中的表。
★ResultSet. CONCUR_UPDATABLE: 能用结果集更新数据库中的表。
(3) 滚动查询经常用到 ResultSet 的下述方法:
public boolean previous() : 将族标品上移动,当移到结果集第一行前面时,返回 false。
public void beforeFirst() : 将游标移动到结果集的初始位置,即在第一行之前。
public void afterLast() : 将游标移到结果集最后一行之后。
public void first() : 将游标移到结果集的第一行。
public void last() : 将游标移到结果集的最后一行。
public boolean isAfterLast() : 判断游标是否在最后一行之后。
public boolean isBeforeFirst() : 判断游标是否在第一行之前。
public boolean isFirst() : 判断游标是否指癌结果集的第一行。
public boolean isLast(): 判断游标是否指加结果集的最后一行。
public int getRow(): 得到当前游标所指行的行号,行号从1开始。如果结果集没有行,返回 0。
public boolean absolute(Cint row) : 将游标移到参数 row 指定的行号。
8.3.3、条件查询
★where子语句
select 字段 from 表名 where 条件
★排序
用 order by 子语句对记录排序,
select * from 表名 order by 字段名(列名)
select * from表名 where 条件 order by 字段名(列名)
8.4、更新、添加与删除记录
Statement 对象调用方法:
public int executeUpdate( String sqlStatement ) ;
通过参数 sqlStatement 指定的方式实现对数据库表中记录的更新.添加和删除操作。方法执行成功(成功更新.添加或删除) ,将返回一个正整数,否则返回 0。
(1)更新
update 表 set 字段 = 新值 where <条件子句>
(2)添加
insert into 表(字段列表) values (对应的具体的记录)
或
insert into 表 values (对应的且体的记录)
(3)删除
delete fronm 表名 where <条件子句>
8.5、用结果集操作数据库中的表
8.5.1、更新记录
使用结果集更新数据库表中第 n 行记录中某列的值的步骤如下 。
(1) 游标移动到第 n行。结果集 rs 调用 absolute()方法将游标移到第 n 行:
rs.absolute(n) ;
(2) 结果集 rs 将第 n行的 column 列的列值更新。结果集可以使用下列方法更新列值:
updateInt(String column,int x) ,updateInt( int column int x)
updateLong(String column,1ong x) ,updateLong( int column,1Long )
updateDouble(String column, double x),updateDoublel( int column,double x)
updateString(String column,String x),updateString( int column, String )
updateDate(String column,Date x),updateDate( int column,Date x)
(3) 更新数据库中的表。最后,结果集 rs 调用 updateRow()方法用结果集中的第 n 行更新数据库表中的第 n 行记录。
以下代码片段按照上述步又,更新 bookList 表中的第 3 行记录的 name 列(字段)的值。
rs.absolute(3) ;
rs.updateString(2, “操作系统”) ; //也可以写成 rs.updateString(“name”, “操作系统”) ;
rs.updateRow( ) ;
8.5.2、插入记录
使用结果集回数据库表中插入(添加)一行记录步骤如下 :
(1) 将结果集 rs 的游标移动到插和人人行。结果集中有一个特殊区域,用作构建要搬入的行的暂存区域,习惯上将该区域位置称作结果集的插入行。为了辐数据库表中插入一行新的记录 ,必须首先将结果集的游标移动到搬入行,代码如下:
rs.moveToInsertRow( ) ;
(2) 更新搬人行的列值,即设置搬入行的列值。结果集可以用 updateXxx()方法更新搬人入行的列值,例如,准备插入的记录是(‘7307014659 ’ ,‘数据结构’, 58 ,’ 2020-08-107 ,那委执行下列操作 :
rs.updateString(1,“7307014659” ) ;
rs.updateString(2, “数据结构”) ;
rs.updateFloat(3,58) ;
rs.updateDate(4,‘2020–08–10’);
(3) 搬入记录。结果集调用 insertRow()方法用结果集中的插和信行问数据库表中插入一行新记录。
8.6、预处理语句
Java 提供了更高效率的数据库操作机制 ,就是 PreparedStatement 对象 ,该对象被习惯地称作预处理语句对象。本节学习怎样使用预处理语句对象操作数据库中的表。
8.6.1、预处理语句的优点
如果不断地向数据库提交 SQL 语句势必增加数据库中 SQL 解释器视频讲解 ”的负担,影响执行的速度。如果应用程序能针对连接的数据库,事先就将 SQL 语句解释为数据库底层的内部命令,然后直接让数据库去执行这个命令,显然不仅减轻了数据库的负担,而且也提高了访问数据库的速度。
Connection 连接对象 con 调用 prepareStatement(CString sql)方法:
PreparedStatement pre = con. prepareStatement( String sq]l ) ;
对参数 sql 指定的 SQL 语句进行预编译处理,生成该数据库底层的内部命令,并将该命令圭装在PreparedStatement 对象 pre 中 ,那么该对象调用下列方法都可以使得该底层内部命令被数据库执行:
ResultSet executeOuery( )
boolean execute() (执行成功返回 false)
int executeUpdate() (执行成功返回 1)
只要编译好了 PreparedStatement 对象 pre,那么 pre 可以随时执行上述方法,显然提高了访问数据库的速度。
8.6.2、使用通配符
在对 SQL 进行预处理时可以使用通配符? (英文问号)来代替字段的值,只要在预处理语句执行之前再设置通配符所表示的具体值即可。例如
Pre = con. PrepareStatement( "SELECT * FROMbookList WHERE price<? ”);
那么在 pre 对象执行之前,必须调用相应的方法设置通配符? 代表的具体值,
Pre. setFloat(1,65) ;
指定上述预处理语句 pre 中通配符? 代表的值是 65。
8.7、事务
事务由一组 SQL 语句组成。所谓*事务处理?是指应用程序保证事务中的 SQL 语句要么全部都执行,要么一个都不执行。
JDBC 事务处理步又如下 :
(1) 用 setAutoCommit(boolean b)方法关闭自动提交模式
事务处理的第一步骤是使用 setAutoCommit(boolean autoCommit)方法关闭自动提交模式。这样做的理由是,和数据库建立连接的对象 con 的提交模式是自动提交模式,即该连接con 产生的 Statement 或 PreparedStatement 对象对数据库提交任何一个 SQL 语句操作都会立刻生效 ,使得数据库中的数据发生变化,这显然不能满足事物处理的要求。例如 ,在转账操作时 ,将用户 geng 的 userMoney 的值由原来的 100 更改为 50(减去 50 的操作)的操作不应当立刻生效,而应等到 zhang 的用户的 userMoney 的值由原来的 20 更新为 70(增加 50 的操作 )后一起生效。如果第 2 个语句 SQL 语句操作未能成功,那么第一个 SQL 语句操作就不应当生效。因此,为了能进行事务处理,必须关闭 con 的自动提交模式(自动提交模式是连接 con的默认设置)。连接 con 首先调用 setAutoCommit (boolean autoCommit ) 方法,将参数autoCommit 取值为 false来关闭自动提交模式 :
con. setRAutoCommit(false) ;
(2)用 commit()方法处理事务
连接 con 调用 setAutoCommit(false)后,产生的 Statement 对象对数据库提交任何一个SQL 语句操作都不会立刻生效,这样一来,就有机会让 Statement 对象(PreparedStatement 对象)提交多个 SQL 语句,这些 SQL 语句就是一个事务。事务中的 SQL 语句不会立刻生效,直到连接 con 调用 commit()方法。con 调用 commit()方法就是让事务中的 SQL 语句全部生效。
(3)用 rollback()方法处理事务失败
连接 con 调用 commit()方法进行事务处理时,只要事务中任何一个 SQL 语句没有生效,就抛出 SQLException 异常。在处理 SQLException 异稼时,必须让 con 调用 rollback()方法,其作用是: 撤销事务中成功执行过的 SQL 语句对数据库数据所做的更新.插入或删除操作 ,即撤销引起数据发生变化的 SQL 语句操作,将数据库中的数据恢复到 commit()方法执行之前的状态。
8.8、使用连接池
8.8.1、连接池简介
Web 应用程序必须首先和数据库建立连接,即得到 Connection 对象,才能进行后续的操作 ,例如查询.更新.添加记录等操作。和数据库建立连接属于比较耗os 时的操作 ,连接池的思想是,由一个管理者,例如 Tomcat 服务器,事先建立好若干个连接,即创建各和干个 Connection 对象放在一起(存放在一个实现 DataSource 接口的对象中) ,称作一个连接池。当 Web 应用程序需要连接数据库时,只需到连接池中获得一个 Connection 对象即可。当 Web 应用程序不再需要 Connection 对象时,就让 Connection 对象调用 close()方法,这样就可以把这个 Connection 对象再返回到连接池中,以便其他 Web 应用程序使用这个 Connection 对象。需要注意的是,Tomcat 服务需提供的连接池中的Connection 对象调用 close()方法不会关闭和数据库的TCP连接,其作用仅仅是把Connection 对象返回到连接池(这一点和 Web 应用程序自己创建的 Connection 对象不同,其原理不必深究) 。简单地说,连接池可以让 Web 应用程序方便地使用 Connection 对象(用完务必放回) ,再用再取,节省了创建 Connection 的时间,提高了 Web 应用程序访问数据库的效率。
8.8.2、建立连接池
(1)连接池配置文件
为了让 Tomcat 服务器创建连接池 ,必须编写一个 XML 文件,Tomcat 服务器通过读取该文件创建连接池。XML 文件的名字必须是 context. xml。内容如下 :
context. Xml
<?xml verslion = "1.0”encoding= "utf -8”?>< Context >
< Resource>
name = “gxv
type = “Javax. sql1.DataSource””
driverClassName = “com.mysql.c]j. jdbc. Driver”
url =” jdbc:mysql://127.0.0.1:3306/bookDatabase?useSSL = false
& amp; serVverTimezone = CST&characterFEncoding= utf 一8”
Username = “root”
password = " "
maxRActive = “15”
maxIdle = "15”
minIdle = “1”
maxWait = "1000”
/>
< /Context >
将连接池配置文件 context. xml 文件保存在 Web 服务目录的 META-INEF 子目录中。例如,对于 Web 服务目录 ch8 ,需要在 ch8 下新建一个子目录 META-INF(字母大写) ,将连接池配置文件 context. xml 保存在\ch8\META-INF\目录路径下(不必重新启动 Tomcat 服务吉) 。Tomeat 服务器会立刻读取 context. xml,创建连接池。如果修改 context. xml 文件,重新保存,Tomcat 服务融会立刻再次读取 context. xml,创建连接池。
连接池配置文件 context. xml 中的 Resource 标记(元素)通知 Tomcat 服务器创建数据源(连接池) ,Resource 标记中各个属性的意义如下 :
(1) name: 设置连接池的名字(命名一个喜欢的名字即可) ,例如 gxy,该名字是连接池的id,context. xml 文件中 ,如果有多个 Resource 标记(一个 Resource 标记对应一个连接池) ,必须保证这些 Resource 标记中的 name 互不相同,即 context. xml 文件可以给出多个不同连接池的配置信息。
(2) type: 设置连接池的类型 ,这里必须是 javax. sql. DataSource ,即 Tomcat 服务需把创建的 Connection 对象存放在实现 DataSource 接口的对象中,即连接池是一个 DataSource 型对象。Tomeat 服务器使用 org. apache. tomcat. dbcp. dbcp2 包中的 BasicDataSource 类创建连接池(包含该包的 jar 文档在 Tomcat 安装目录的\lib 子目录中) 。
(3) driverClassName: 设置数据库连接需,即数据库驱动的类。如果是为 MySQL 8. 0 数据库建立连接池, driverClassName 的值就是 com. mysql. cj. jdbc. Driver (MySQL 5. 6 是com. mysdql. jdbc. Driver) ,如果是 SQL Server 数据库 ,其值是 com. microsoft. sqlserver. jdbc.SQLServerDriver ,如果是 Access 数据库 ,其值是 com. hxtt. sql. access. AccessDriver。不要坏记把相应的数据库连接需保存到 Tomcat 安装目录下的1lib 文件夹中,例如,把 JDBC-MySQL数据库连接器 mysql-connector-java-8.0. 18. jar 保存到 Tomcat 安装目录下的1lib 文件夹中,并重新启动了 Tomcat 服务需。
(4) url: 设置连接数据库的 URL ,注意 url 要小写。需要注意的是对于 url 中的 亿 字符要写成“&”,这是 XML 文件对特殊字符的一个特殊规定。
(5) username: 给出可以访问数据库的用户名,例如 root。
(6) password: 给出访问数据库的密码,例如,root 用户的默认密码是无密码。
(7) maxActive: 设置连接池的大小,即连接池中处于活动状态 Connection 对象的数目(Tomeat 服务器创建的 Connection 对象的最大数目)。maxActive 取值不可以超过数据库系统人允许的最大连接数目(同一时刻允许的最多连接数目,细节参看有关数据库系统的说明)。在设计 Web 应用程序时,通过使用连接池 ,不仅可以提高访问数据库的效率,也可以防止数据库系统连接数目过多导致数据库系统性能下降。取值 0 表示不受限制。
(8) maxIdle: 设置连接池中可处于空闲状态的 Connection 对象的最大数目,取值非正整数,例如 0,表示不限制,如果取正整数,例如6,那么当空闲状态的 Connection 对象多余 6 个时,Tomcat 服务器会释放多余的 Connection 对象,即从连接池中删除某些 Connection 对象 。
(9) minIdle : 设置连接池中保证处于空闲状态的 Connection 对象的最小数目。例如 ,取值 1 ,当连接池中仅仅剩下两个空闲状态 Connection 对象时 ,此刻如果同时有两个用户需要使用连接池中的 Connection 对象 ,那么二者只能有一个获得 Connection 对象 ,另一个用户必须等待(因为 Tomecat 服务需必须保证连接池中有 1 个 Connection 对和象空闲) 。
(10) maxWait: 设置连接池中没有空闲状态 Connection 对象可用时,用户请求获得连接池中 Connection 对象需要等待的最长时间(单位是毫秒) ,如果超出 maxWait 设置的时间,Tomcecat 服务器将抛出一个 TimeoutException 给用户。取值负数,例如一1,表示用户可以无限时等待。
(2)使用连接池
应用程序必须到 Tomcat 服务需中去获得连接池。步骤如下 :
(1) Context 接口 。
首先创建一个实现 Context(上下文)接口的对象 :
Context context = new InitialContext( ) ;
然后让 context 去寻找 Tomceat 服务需曾绑定在运行环境中的另一个 Context 对象 ;
Context contextNeeded = (Context)context. lookup(" java:compVenv" ) ;
其中的 java:compyenv 是 Tomcat 服务需绑定这个 Context 对象时使用的资源标志符(不可以写错) 。
(2) 得到连接池 。
Tomecat 服务需通过连接池配置文件 context. xml 将连接池绑定在 Context 对和象contextNeeded 中(见步骤(1))。绑定用的资源标志符是连接池配置文件 context. xml 中name 给的值,例如 gxy。因此,从 contextNeeded 中获得连接池的代码是:
DataSource ds = (DataSource)contextNeeded. lookup(“gxV” ) ;
(3) 从连接池中获得连接。
获得连接池之后,就可以从连接池中获得 Connection 对象。连接池中都是已经创建好的Connection 对象 ,连接池调用 getConnection()方法,如果有空闲的 Connection 对象 ,该方法就返回一个 Connection 对象,如果没有空闲的 Connection 对象,该方法将使得用户线程处于waiting 状态,即等待该方法返回 Connection 对象(见连接池配置文件 context. xml 中maxWait 值的设置)。代码如下 :
Connection con = ds. getConnection( ) ;
(4) 将连接返回连接池 。
当 Web 应用程序不再需要 Connection 对象时,就让 Connection 对象调用 close()方法,这样就可以把这个 Connection 对象再放回连接池中,以便其他 Web 应用程序使用这个Connection 对象。如果用户都忘记 Connection 对象再返回连接池中,将可能很快导致连接池中无 Connection 对象可用。