1. 數據源的定義:
數據源是數據庫連接池裏面的概念,連接池就是指當服務器啓動時,先建立幾個連接,在應用需要與數據庫連接時,就從連接池裏獲取,使用完以後,不是將連接斷掉,而是放回到池裏面,這樣就減少了數據連接創建的次數,大大提高了連接性能。而數據源就是給服務器一個配置信息,然服務器就知道怎麼使用JDBC驅動,比如url參數,數據庫實例名、用戶名與密碼等等。Java中的數據源就是javax.sql.DataSource。DataSource的創建可以有不同的實現,下面以mysql爲例介紹幾種常見DataSource的創建方法:
導入jar包:commons-dbcp.jar和commons-pool.jar和mysql-connector-java-5.1.39-bin.jar
推薦網址:
http://blog.csdn.net/peichuangaoling/article/details/45893391
http://blog.csdn.net/navy_xue/article/details/13090945
2. 配置數據庫連接池使用之JNDI的方式
2.1 JNDI:
JNDI就是(JavaNaming and Directory Inteface)Java名稱目錄接口。
JNDI的作用:就是將資源引入到服務器中。可以將JNDI當成一個倉庫。將Java對象放入到JNDI中去。
2.2 數據源的由來:
在java開發中,使用JDBC操作數據庫的幾個步驟:
1.使用Class.forName(類的全路徑名稱):用於加載數據庫驅動程序。
2.獲得數據庫的Connection連接對象。DriverManager.getConnection()。
3.操作數據庫:查詢數據庫,或者更新數據庫內容,
4.關閉數據庫連接:使用close方法。
注意:每次獲取一個數據庫連接的要經過這4個步驟,但是其中【1】,【2】,【4】是所有操作數據庫的公共操作,只有【3】是操作數據庫的不同步驟。並且獲得數據庫的connection對象和關閉數據庫的連接都是要一定的時間。造成性能較差。
如果我們一開始就有已經創建好了多個connection對象,放在一個公共地方,當有一個連接數據庫的請求,就從這個公共地方中取出一個connection,操作數據庫,操作完成數據庫,不關閉connection,而是放入到公共倉庫中去,這就出現了數據庫連接池的東西,就是存放多個Connection對象的地方。
2.3 使用JNDI配置數據數據庫連接池有兩種方式(全局JNDI配置和非全局JNDI配置)
如果需要配置全局的 Resource,則在server.xml的GlobalNamingResources節點裏加入Resource,再在Context節點裏加入ResourceLink的配置。
全局的resource只是爲了重用,方便所有該tomcat下的web工程的數據源管理,但如果你的tomcat不會同時加載多個web工程,也就是說一個tomcat只加載一個web工程時,是沒有必要配置全局的resource的。
每個web工程一個數據源:
在$CATALINA_HOME/conf/context.xml的根節點Context里加入Resource配置。這種配置方法,你在context.xml配置了一個數據源,但Tomcat中有同時運行着5個工程,那了就壞事兒了,這個在Tomcat啓動時數據源被創建了5份,每個工程1份數據源。連接數會是你配置的參數的5倍。
只有在你的Tomcat只加載一個web工程時,纔可以直接以context.xml配置數據源。
2.3.1 全局JNDI配置
在Tomacat的conf/context.xml中的內容:
<context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<!-- 配置mysql數據庫的連接池 -->
<Resource name="jdbc/mysql"
author="Container"
type="javax.sql.DataSource"
maxActive="4"
maxIdle="2"
maxWait="10000"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mysqltest" />
</context>
2.3.2 非全局JNDI配置
他只針對某一個Web項目的數據源的配置
1.導入要鏈接數據庫的jar包文件。
例如sqlserver導入:sqljdbc4.jar包
Oracle導入:ojdbc14.jar包
配置Oracle數據庫的JNDI數據源
<Resource
name="jdbc/oracle"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="lead_oams"
password="p"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@192.168.1.229:1521:lead"/>
配置SQLServer數據庫的JNDI數據資源
<Resource
name="jdbc/sqlserver"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="sa"
password="123456"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://192.168.1.51:1433;DatabaseName=demo"/>
</Context>
MySQL導入:mysql-connector-java-5.0.8.jar包
配置MySQL數據庫的JNDI數據資源:
<Resource name="jdbc/mysql"
author="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mysqltest" />
2.在JNDI中配置數據庫的連接池:
2):在web項目的META-INF下 建立context.xml文件
context.xml內容:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/mysql"
author="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mysqltest" />
</Context>
說明:
上文中的設置的 maxActive="4"說明可以最大連接的個數爲4個,再建立連接,則出現異常。
而maxIdle="2"說明當關閉數據庫時(不是真正的斷開連接,而是歸還連接池中)連接池中最大可以有空閒的連接數爲2個。
若是再有建立連接,此時若連接池中沒有空閒的連接,但是又沒有達到maxActive併發的最大連接數,則在連接池中建立連接。
3): 在Tomcat的conf/server.xml中配置:
找到:
配置
<Resource name="jdbc/mysql"
author="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="liukunlun"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://loaclhost:3306/fuxi" />
如圖:
然後在Tomcat的conf/context.xml中配置 <ResourceLink name="jdbc/mysql" global="jdbc/mysql" type="javax.sql.DataSource"/> 如圖:
上訴3箇中法配置完成後最後都要配置web.xml內容 (在web應用中引用JNDI資源)
<resource-ref>
<!-- 對該資源的描述語言 -->
<description> dbcpconnect</description>
<!-- 引用的資源名,必須與context.xml中的名字一致 -->
<res-ref-name> jdbc/mysql</res-ref-name>
<!-- 資源類型 -->
<res-type>javax.sql.DataSource</res-type>
<!-- 管理權限 -->
<res-auth>Container</res-auth>
</resource-ref>
說明:
description :描述 (可隨便寫)
res-ref-name : java:/comp/env 下面的相關的名字
res-type : 資源的類型,資源管理器連接工廠的全限定名稱。
res-auth : 資源需要的權限管理。 分兩種:Application或 container
紅色字體必須與java文件中的相一致
4):在Tomcat的conf/server.xml中配置虛擬目錄時配置
在配置虛擬目錄時,也就是在配置conf下面的server.xml時,在context標籤內添加池配置.
在tomcat\conf下server.xml中找到
在其中添加:<Context path="/website" docBase="F:/JAVA/String/shujuyuan" reloadable="true">
如圖:
注意:
docBase要改成你的項目目錄。
path爲虛擬路徑,訪問時的路徑,注意:一定要加“/”
配置虛擬目錄
在context 節點下配置
<Resource
name="jdbc/mysql"
author="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="liukunlun"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://loaclhost:3306/fuxi" />
如圖:
配置好後只需重啓服務器,無需在web.xml文件中配置 。
參數設置:
name 表示指定的jdbc,jndi名稱 ,通常採用jdbc/**方式
auth 管理權限,指定管理Resource的Manager,可以是Container或application(倆者固定使用)
type 指出Resource所屬的類名,是什麼類型的數據源,使用標準的javax.sql.DataSource
maxActive 默認值是 8, 連接池中同時可以分派的最大活躍連接數,設爲0表示無限制
maxIdle 連接池中最多可空閒的連接數 默認是 8
maxWait 爲連接最大的等待時間,單位毫秒,如果超過此時間將接到異常。設爲-1表示無限制
username 表示數據庫用戶名
password 表示數據庫用戶的密碼
driverClassName 數據庫驅動
url 數據庫連接url
testWhileIdle : 默認值是 false, 當連接池中的空閒連接是否有效
<!-- (紅色字體爲常用參數設置)-->
logAbandoned 表示被丟棄的數據庫連接是否做記錄,以便跟蹤
removeAbandonedTimeout : 默認值是 300( 秒), 活動連接的最大空閒時間
removeAbandoned : 默認值是 false, 是否清理 removeAbandonedTimeout 秒沒有使用的活動連接 , 清理後並沒有放回連接池
logAbandoned : 默認值 false, 連接池收回空閒的活動連接時是否打印消息
testOnBorrow : 默認值是 true ,當從連接池取連接時,驗證這個連接是否有效
testOnReturn : 默認值是 flase, 當從把該連接放回到連接池的時,驗證這個連接是否有效
timeBetweenEvictionRunsMilis : 默認值是 -1 ,單位是毫秒,每隔一段多少毫秒跑一次回收空閒線程的線程
minEvictableIdleTimeMilis : 默認值是 1000 * 60 * 30(30 分鐘 ) ,單位毫秒,連接池中連接可空閒的時間
numTestsPerEvictionRun : 默認值是 3 ,每次驗證空閒連接的連接數目
connectionInitSqls : 默認值是 null, 一組用來初始化連接的 sql 語句,這些語句只在連接工廠創建連接時執行一次。
validationQuery : 一條 sql 語句,用來驗證數據庫連接是否正常。這條語句必須是一個查詢模式,並至少返回一條數據。一般用“ select 1 ”
initialSize : 默認值是 0, 連接池創建連接的初始連接數目
minIdle : 默認是 0, 連接數中最小空閒連接數
注意:
minEvictableIdleTimeMilis和removeAbandonedTimeout參數,這兩個參數針對的連接對象不一樣,
minEvictableIdleTimeMillis 針對連接池中的連接對象 ,
removeAbandonedTimeout 針對未被 close 的活動連接 (被調用,不在池中的連接對象 )
WEB工程中的使用
創建數據源:
正確的配置後,就可以在程序中以JNDI的方式創建數據源,得到數據庫連接並進行相應的操作。代碼如下:
DataSourceManager類
package utils;
import java.sql.Connection;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DataSourceManager {
private static Context context;
private static DataSource dataSource;
static {
try {
// 實例上下文目錄
context = new InitialContext();
// 在命名空間和目錄空間中查找 數據源名稱 返回數據庫連接池對象 JNDI
dataSource=(DataSource)context.lookup("java:comp/env/jdbc/mysql");
} catch (NamingException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
}
JSP中使用
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@page import="java.sql.*, javax.sql.*, javax.naming.*"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>數據</title>
</head>
<body>
<h1>Using a DataSource</h1>
<%
DataSource ds = null;
Connection conn = null;
ResultSet result = null;
Statement stmt = null;
ResultSetMetaData rsmd = null;
try{
Context context = new InitialContext();
Context envCtx = (Context)
context.lookup("java:comp/env");
ds = (DataSource)envCtx.lookup("jdbc/mysql");
if (ds != null) {
conn = ds.getConnection();
stmt = conn.createStatement();
result = stmt.executeQuery("SELECT * FROM student");
}
}
catch (Exception e) {
System.out.println("Error occurred " + e);
}
int columns=0;
try {
rsmd = result.getMetaData();
columns = rsmd.getColumnCount();
}
catch (Exception e) {
System.out.println("Error occurred " + e);
}
System.out.println(columns);
%>
<table width="90%" border="1">
<tr>
<% // write out the header cells containing the column labels
try {
for (int i=1; i<=columns; i++) {
out.write("<th>" + rsmd.getColumnLabel(i) "</th>");
}
%>
</tr>
<%
// now write out one row for each entry in the database table
while (result.next()) {
out.write("<tr>");
for (int i=1; i<=columns; i++) {
out.write("<td>" + result.getString(i) + "</td>");
}
out.write("</tr>");
}
// close the connection, resultset, and the statement
result.close();
stmt.close();
conn.close(); // 將連接重新放回到池中
} catch (Exception e) { // end of the try block
System.out.println("Error " + e);
}finally { // ensure everything is closed
try {
if (stmt != null)
stmt.close();
} catch (Exception e) {}
try {
if (conn != null)
conn.close();
} catch (Exception e) {}
}
%>
</table>
</body>
</html>
Dao類中的使用
DBCP 數據連接池的配置和使用
DBCP(DataBase connection pool),數據庫連接池。是 apache上的一個Java 連接池項目,也是 tomcat使用的連接池組件。
單獨使用dbcp需要3個包:common-dbcp.jar,common-pool.jar,common-collections.jar
由於建立數據庫連接是一個非常耗時耗資源的行爲,所以通過連接池預先同數據庫建立一些連接,放在內存中,應用程序需要建立數據庫連接時直接到連接池中申請一個就行,用
完後再放回去。
獲取數據庫連接的類:DBCP.java
import java.sql.Connection;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
public class DBCP {
private static BasicDataSource basicDataSource = null ;
private static DataSource dataSource = null;
static{
basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3306/fuxi");
basicDataSource.setUsername("root");
basicDataSource.setPassword("liukunlun");
basicDataSource.setLogAbandoned(true);
basicDataSource.setMaxIdle(30);
basicDataSource.setInitialSize(50);
dataSource = basicDataSource;
}
public static Connection getConnection() {
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
}
配置文件的 DBCO連接池的配置
連接數據庫信息的配置文件:dbcp.properties
dbcp.driverClassName=com.mysql.jdbc.Driver
dbcp.url=jdbc:mysql://localhost:3306/fuxi
dbcp.username=root
dbcp.password=liukunlun
dbcp.initialSize=30
dbcp.minIdle=10
dbcp.maxIdle=10
dbcp.maxWait=1000
dbcp.maxActive=30
獲取數據庫連接池的類
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
public class DbcpConnection {
private static DataSource dataSource;
private static Connection connection;
public static void initDataSource(){
FileInputStream is = null;
Properties properties = new Properties();
String driverClassName = null;
String url = null;
String username = null;
String password = null;
int initialSize = 0;
int minIdle = 0;
int maxIdle = 0;
int maxWait = 0;
int maxActive = 0;
try {
String path = System.getProperty("user.dir")+"\\src\\com\\xiami\\db\\connection\\";
is = new FileInputStream(path+"dbcp.properties");
properties.load(is);
driverClassName = properties.getProperty("dbcp.driverClassName");
url = properties.getProperty("dbcp.url");
username = properties.getProperty("dbcp.username");
password = properties.getProperty("dbcp.password");
initialSize = Integer.parseInt((properties.getProperty("dbcp.initialSize").trim()));
minIdle = Integer.parseInt((properties.getProperty("dbcp.minIdle")).trim());
maxIdle = Integer.parseInt((properties.getProperty("dbcp.maxIdle")).trim());
maxWait = Integer.parseInt((properties.getProperty("dbcp.maxWait")).trim());
maxActive = Integer.parseInt((properties.getProperty("dbcp.maxActive")).trim());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException ioe){
ioe.printStackTrace();
}finally{
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
BasicDataSource bds = new BasicDataSource();
bds.setUrl(url);
bds.setDriverClassName(driverClassName);
bds.setUsername(username);
bds.setPassword(password);
bds.setInitialSize(initialSize);
bds.setMaxActive(maxActive);
bds.setMinIdle(minIdle);
bds.setMaxIdle(maxIdle);
bds.setMaxWait(maxWait);
dataSource = bds;
}
public static Connection getConnection() throws SQLException {
if (dataSource == null) {
initDataSource();
}
Connection conn = null;
if (dataSource != null) {
conn = dataSource.getConnection();
}
return conn;
}
}
在Service層使用的時候:ZhiDianJieDu.java (業務邏輯處理的類)
package utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
public class Duquxinxi{
private Statement stmt = null;
private ResultSet result = null;
private ResultSetMetaData rsmd = null;
private Connection conn = null;
public void test() {
try {
conn = DBCP.getConnection();
System.out.println("連接成功!");
stmt = conn.createStatement();
result = stmt.executeQuery("SELECT * FROM fuxi");
} catch (Exception e) {
System.out.println(e);
}
int columns = 0;
try {
rsmd = result.getMetaData();
columns = rsmd.getColumnCount();
} catch (Exception e) {
System.out.println("Error occurred " + e);
}
try {
for (int i = 1; i <= columns; i++) {
System.out.println(rsmd.getColumnLabel(i));
}
while (result.next()) {
for (int i = 1; i <= columns; i++) {
System.out.println(result.getString(i));
}
System.out.println();
}
// close the connection, resultset, and the statement
// 關閉連接,resultset,聲明
result.close();
stmt.close();
conn.close();
} // end of the try block
catch (Exception e) {
System.out.println("Error " + e);
}
// ensure everything is closed 確保一切都是封閉的
finally {
try {
if (stmt != null)
stmt.close();
} catch (Exception e) {
}
try {
if (conn != null)
conn.close();
} catch (Exception e) {
}
}
}
}
C3P0 數據庫連接池的配置和使用
C3p0.properties 位置
內容
#jdbc基本信息
driverClass=org.gjt.mm.mysql.Driver
jdbcUrl=jdbc:mysql://localhost:3306/fuxi
user=root
password=liukunlun
#c3p0連接池信息
c3p0.minPoolSize=3
c3p0.maxPoolSize=25
#當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數
c3p0.acquireIncrement=3
#定義在從數據庫獲取新連接失敗後重復嘗試的次數
c3p0.acquireRetryAttempts=60
#兩次連接中間隔時間,單位毫秒
c3p0.acquireRetryDelay=1000
#連接關閉時默認將所有未提交的操作回滾
c3p0.autoCommitOnClose=false
#當連接池用完時客戶端調用getConnection()後等待獲取新連接的時間,超時後將拋出#SQLException,如設爲0則無限期等待。單位毫秒
c3p0.checkoutTimeout=3000
#每120秒檢查所有連接池中的空閒連接。Default: 0
c3p0.idleConnectionTestPeriod=120
#最大空閒時間,60秒內未使用則連接被丟棄。若爲0則永不丟棄。Default: 0
c3p0.maxIdleTime=600
#如果設爲true那麼在取得連接的同時將校驗連接的有效性。Default: false
c3p0.testConnectionOnCheckin=true
#c3p0將建一張名爲c3p0TestTable的空表,並使用其自帶的查詢語句進行測試。
jdbc.automaticTestTable = c3p0TestTable
C3P0ConnentionProvider.Java
package utils;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.DataSources;
/**
* c3p0連接池管理類
*/
public class C3P0ConnentionProvider {
private static final String JDBC_DRIVER = "driverClass";
private static final String JDBC_URL = "jdbcUrl";
private static DataSource ds;
/**
* 初始化連接池代碼塊
*/
static {
initDBSource();
}
/**
* 初始化c3p0連接池
*/
private static final void initDBSource() {
Properties c3p0Pro = new Properties();
try {
// 加載配置文件
String path = C3P0ConnentionProvider.class.getResource("/").getPath();
String websiteURL = (path.replace("/build/classes", "").replace("%20"," ").replace("classes/", "") + "c3p0.properties").replaceFirst("/", "");
FileInputStream in = new FileInputStream(websiteURL);
c3p0Pro.load(in);
} catch (Exception e) {
e.printStackTrace();
}
String drverClass = c3p0Pro.getProperty(JDBC_DRIVER);
if (drverClass != null) {
try {
// 加載驅動類
Class.forName(drverClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Properties jdbcpropes = new Properties();
Properties c3propes = new Properties();
for (Object key : c3p0Pro.keySet()) {
String skey = (String) key;
if (skey.startsWith("c3p0.")) {
c3propes.put(skey, c3p0Pro.getProperty(skey));
} else {
jdbcpropes.put(skey, c3p0Pro.getProperty(skey));
}
}
try {
// 建立連接池
DataSource unPooled = DataSources.unpooledDataSource(c3p0Pro.getProperty(JDBC_URL), jdbcpropes);
ds = DataSources.pooledDataSource(unPooled, c3propes);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 獲取數據庫連接對象
*
* @return 數據連接對象
* @throws SQLException
*/
public static synchronized Connection getConnection() throws SQLException {
final Connection conn = ds.getConnection();
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
return conn;
}
}
使用
datasource2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@page import="utils.*"%>
<%@page import="java.sql.*, javax.sql.*, javax.naming.*"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
Statement stmt = null;
ResultSet result = null;
ResultSetMetaData rsmd = null;
Connection conn = null;
try{
conn = C3P0ConnentionProvider.getConnection();
//conn = DataSourceManager.getConnection();
out.println("連接成功!");
stmt = conn.createStatement();
result = stmt.executeQuery("SELECT * FROM fuxi");
} catch (Exception e) {
out.println(e);
}
int columns=0;
try {
rsmd = result.getMetaData();
columns = rsmd.getColumnCount();
}
catch (Exception e) {
System.out.println("Error occurred " + e);
}
%>
<table width="90%" border="1">
<tr>
<% // write out the header cells containing the column labels 寫出標題單元格包含列標籤
try {
for (int i=1; i<=columns; i++) {
out.write("<th>" + rsmd.getColumnLabel(i) + "</th>");
}
%>
</tr>
<% // now write out one row for each entry in the database table 現在寫出一行中的每個條目數據庫表中
while (result.next()) {
out.write("<tr>");
for (int i=1; i<=columns; i++) {
out.write("<td>" + result.getString(i) + "</td>");
}
out.write("</tr>");
}
// close the connection, resultset, and the statement 關閉連接,resultset,聲明
result.close();
stmt.close();
//conn.close();
} // end of the try block
catch (Exception e) {
System.out.println("Error " + e);
}
// ensure everything is closed 確保一切都是封閉的
finally {
try {
if (stmt != null)
stmt.close();
} catch (Exception e) {}
try {
// if (conn != null)
// conn.close();
} catch (Exception e) {}
}
%>
</table>
</body>
</html>