數據源的作用
JDBC操作的步驟:
1、 加載驅動程序
2、 連接數據庫
3、 操作數據庫
4、 關閉數據庫,釋放連接
也就是說,所有的用戶都需要經過此四步進行操作,但是這四步之中有三步對所有人都是一樣的,而所有人只有在操作上是不一樣,那么這就造成了性能的損耗。
那么最好的做法是,准備出一個空間,此空間里專門保存着全部的數據庫連接,以后用戶用數據庫操作的時候不用再重新加載驅動、連接數據庫之類的,而直接從此空間中取走連接,關閉的時候直接把連接放回到此空間之中。
那么此空間就可以稱為連接池(保存所有的數據庫連接),但是如果要想實現此空間的話,則必須有一個問題要考慮?
1、 如果沒有任何一個用戶使用連接,那么那么應該維持一定數量的連接,等待用戶使用
2、 如果連接已經滿了,則必須打開新的連接,供更多用戶使用
3、 如果一個服務器就只能有100個連接,那么如果有第101個人過來呢?應該等待其他用戶釋放連接
4、 如果一個用戶等待時間太長了,則應該告訴用戶,操作是失敗的
如果直接用程序實現以上功能,則會比較麻煩,所以在Tomcat 4.1.27之后,在服務器上就直接增加了數據源的配置選項,直接在服務器上配置好數據源連接池即可。
在J2EE服務器上保存着一個數據庫的多個連接。
每一個連接通過DataSource可以找到。
DataSource被綁定在了JNDI樹上(為每一個DataSource提供一個名字)
客戶端,通過名稱找到在JNDI樹上綁定的DataSource,再由DataSource找到一個連接。
那么在以后的操作中,除了數據庫的連接方式不一樣之外,其他的所有操作都一樣,只是關閉的時候不是徹底地關閉數據庫,而是把數據庫的連接放回到連接池中去。
如果要想使用此配置,則必須配置虛擬目錄,因為此配置是在虛擬目錄之上起作用的。
當然,需要注意的是,如果要想完成以上的功能,在服務器上一定要保存好各個數據庫的驅動程序。
server.xml:
<Context path="/dao" docBase="E:\eclipsedemo\DAOProject\WebRoot"
debug="5" reloadable="true" crossContext="true">
<Resource name="jdbc/oracle"
auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="scott" password="tiger"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@localhost:1521:MLDN"/>
</Context>
只要在服務器上使用以上的配置,就表示配置好連接池了,那么在配置之中,有以下幾個主要的屬性需要注意:
• <Resource>中定義的是資源的配置使用
|- name:表示以后要查找的名稱。通過此名稱可以找到DataSource,此名稱任意更換,但是程序中最終要查找的就是此名稱,為了不與其他的名稱混淆,所以使用jdbc/oracle,現在配置的是一個jdbc的關於oracle的命名服務。
|- auth:由容器進行授權及管理,指的用戶名和密碼是否可以在容器上生效
|- type:此名稱所代表的類型,現在為javax.sql.DataSource
|- maxActive:表示一個數據庫在此服務器上所能打開的最大連接數
|- maxIdle:表示一個數據庫在此服務器上維持的最小連接數
|- maxWait:最大等待時間。10000毫秒
|- username:數據庫連接的用戶名
|- password:數據庫連接的密碼
|- driverClassName:數據庫連接的驅動程序
|- url:數據庫連接的地址
但是,在Tomcat 5.5之后的服務器,如果要想正確的使用此數據源連接,則必須在web.xml中進行一系列的配置。
web.xml:
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/oracle</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
以上表示配置的資源引用:
• res-ref-name:表示引用資源的名稱
• res-type:此資源對應的類型為javax.sql.DataSource
• res-auth:容器授權管理
如果配置完數據源連接池之后,就可以按照以下的步驟進行訪問:
• 初始化名稱查找上下文
• 通過JNDI名稱找到DataSource
• 通過DataSource取得一個連接
• 操作數據庫
• 關閉數據庫,關閉的時候是將連接放回到連接池之中。
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@ page import="java.sql.*,javax.sql.*,javax.naming.*"%>
<html>
<head>
<title>My JSP 'MyJsp.jsp' starting page</title>
</head>
<body>
<%
Context ctx = new InitialContext() ;
DataSource ds = (DataSource)ctx.lookup("jdbc/oracle") ;
Connection conn = ds.getConnection() ;
%>
<%=conn%>
<%
conn.close() ;
%>
</body>
</html>
但是以上代碼運行時發生了以下的錯誤:
javax.servlet.ServletException: Name jdbc is not bound in this Context
此錯誤的提示是,找不到名稱。
但是,所有的名稱都已經配置正確了,為什么還不能訪問呢?
• 在JAVA EE中對於所有的名稱訪問前都應該設置一個環境屬性:java:comp/env/名稱,有些服務器已經自動設置好了此屬性,所以直接訪問名稱即可,但是Tomcat並沒有自動設置好,所以在訪問連接的時候,連接地址要換成:java:comp/env/jdbc/oracle
<%
Context ctx = new InitialContext() ;
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/oracle") ;
Connection conn = ds.getConnection() ;
%>
<%=conn%>
<%
conn.close() ;
%>
則以后在使用DataBaseConnection的時候,就直接使用DataSource連接了。
DataBaseConnection.java:
package org.lxh.oracle.dbc;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DataBaseConnection {
private static final String JNDINAME = "java:comp/env/jdbc/oracle";
private Connection conn = null;
public DataBaseConnection() {
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(JNDINAME);
conn = ds.getConnection();
} catch (NamingException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public Connection getConnection() {
return this.conn;
}
public void close() {
if (this.conn != null) {
// 如果不為空,則表示數據庫已經打開了
try {
this.conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
總結
使用連接池可以提升數據庫的訪問性能,但是在使用數據庫連接池的時候,需要注意的是,連接池是在Tomcat上配置的,所以必須在Tomcat中才可以取得連接。
