JDBC數(shù)據(jù)源連接池配置及應(yīng)用
使用JDBC建立數(shù)據(jù)庫連接的兩種方式:
1.在代碼中使用DriverManager獲得數(shù)據(jù)庫連接。這種方式效率低,并且其性能、可靠性和穩(wěn)定性隨著用戶訪問量得增加逐漸下降。
2.使用配置數(shù)據(jù)源的方式連接數(shù)據(jù)庫,該方式其實(shí)質(zhì)就是在上述方法的基礎(chǔ)上增加了數(shù)據(jù)庫連接池,這種方式效率高。
數(shù)據(jù)源連接池的方式連接數(shù)據(jù)庫與在代碼中使用DriverManager獲得數(shù)據(jù)庫連接存在如下差別:
1)數(shù)據(jù)源連接池的方式連接數(shù)據(jù)庫是在程序中,通過向一個JNDI(Java Naming and Directory Interface)服務(wù)器查詢,即調(diào)用Context接口的lookup()方法,來得到DataSource對象,然后調(diào)用DataSource對象的getConnection()方法建立連接
2)為了能重復(fù)利用數(shù)據(jù)庫連接對象,提高對請求的響應(yīng)時間和服務(wù)器的性能,采用連接池技術(shù).連接池技術(shù)預(yù)先建立多個數(shù)據(jù)庫連接對象,然后將連接對象保存到連接池中,當(dāng)客戶請求到來時,從池中取出一個連接對象為客戶服務(wù),當(dāng)請求完成時,客戶程序調(diào)用close()方法,將連接對象放回池中.
3)在代碼中使用DriverManager獲得數(shù)據(jù)庫連接的方式中,客戶程序得到的連接對象是物理連接,調(diào)用連接對象的close()方法將關(guān)閉連接,而采用連接池技術(shù),客戶程序得到的連接對象是連接池中物理連接的一個句柄,調(diào)用連接對象的close()方法,物理連接并沒有關(guān)閉,數(shù)據(jù)源的實(shí)現(xiàn)只是刪除了客戶程序中的連接對象和池中的連接對象之間的聯(lián)系.
為了測試方便可以在數(shù)據(jù)庫(這里以mysql 5為例)中建立一個USER表:
CREATE TABLE `user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `password` varchar(50) DEFAULT NULL, `email` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`), );
導(dǎo)入數(shù)據(jù)庫的驅(qū)動的jar包到tomcat的lib目錄下(這里以mysql5為例,所用到的jar包為:mysql-connector-java-5.0.8-bin.jar)。
1.在代碼中使用DriverManager獲得數(shù)據(jù)庫連接。這種方式效率低,并且其性能、可靠性和穩(wěn)定性隨著用戶訪問量得增加逐漸下降。
oracle數(shù)據(jù)庫連接的Java代碼如下:
import java.sql.Connection;
import java.sql.DriverManager;
/**
* 獲取數(shù)據(jù)庫連接
*/
public class DBConnection {
/** Oracle數(shù)據(jù)庫連接URL*/
private final static String DB_URL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
/** Oracle數(shù)據(jù)庫連接驅(qū)動*/
private final static String DB_DRIVER = "oracle.jdbc.driver.OracleDriver";
/** 數(shù)據(jù)庫用戶名*/
private final static String DB_USERNAME = "root";
/** 數(shù)據(jù)庫密碼*/
private final static String DB_PASSWORD = "admin";
/**
* 獲取數(shù)據(jù)庫連接
* @return
*/
public Connection getConnection(){
/** 聲明Connection連接對象*/
Connection conn = null;
try{
/** 使用Class.forName()方法自動創(chuàng)建這個驅(qū)動程序的實(shí)例且自動調(diào)用DriverManager來注冊它*/
Class.forName(DB_DRIVER);
/** 通過DriverManager的getConnection()方法獲取數(shù)據(jù)庫連接*/
conn = DriverManager.getConnection(DB_URL,DB_USERNAME,DB_PASSWORD);
}catch(Exception ex){
ex.printStackTrace();
}
return conn;
}
/**
* 關(guān)閉數(shù)據(jù)庫連接
*
* @param connect
*/
public void closeConnection(Connection conn){
try{
if(conn!=null){
/** 判斷當(dāng)前連接連接對象如果沒有被關(guān)閉就調(diào)用關(guān)閉方法*/
if(!conn.isClosed()){
conn.close();
}
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}
mysql數(shù)據(jù)庫連接的JSP代碼如下:
<%@page import="java.sql.*, com.mysql.jdbc.Driver"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<body>
<%
//com.mysql.jdbc.Driver
Class.forName(Driver.class.getName()).newInstance();
String url = "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF8";
String user = "root";
String password = "123";
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
String sql = "select * from user";
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
out.print("<br />" + "====================" + "<br />");
out.print(rs.getLong("id") + " ");
out.print(rs.getString("username") + " ");
out.print(rs.getString("password") + " ");
out.print(rs.getString("email") + " ");
}
%>
</body>
</html>
2.使用配置數(shù)據(jù)源的方式連接數(shù)據(jù)庫,該方式其實(shí)質(zhì)就是在上述方法的基礎(chǔ)上增加了數(shù)據(jù)庫連接池,這種方式效率高。
1)mysql數(shù)據(jù)庫數(shù)據(jù)源連接池的JSP代碼如下:
<%@page import="java.sql.*, javax.naming.*, javax.sql.DataSource"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<body>
<%
Context initCtx = new InitialContext();
DataSource ds = (DataSource)initCtx.lookup("java:comp/env/jdbc/demoDB");
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
String sql = "select * from user";
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
out.print("<br />" + "====================" + "<br />");
out.print(rs.getLong("id") + " ");
out.print(rs.getString("username") + " ");
out.print(rs.getString("password") + " ");
out.print(rs.getString("email") + " ");
}
%>
</body>
</html>
2) 添加如下代碼到tomcat的conf目錄下的server.xml中:
<Context> <Resource name="jdbc/demoDB" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/demo" username="root" password="123" maxActive="50" maxIdle="30" maxWait="10000" /> </Context>
3)在web工程目錄下的web.xml的根節(jié)點(diǎn)下配置如下內(nèi)容:
<resource-ref> <description>mysqlDB Connection</description> <res-ref-name>jdbc/demoDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
完成上述步驟數(shù)據(jù)源的連接池配置已經(jīng)完成,但是為了提高項(xiàng)目的可移植性,最好將上述第二步的內(nèi)容放入到工程的META-INF目錄的context.xml中(這個文件需要自行建立):
<?xml version="1.0" encoding="UTF-8"?> <Context> <Resource name="jdbc/demoDB" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/demo" username="root" password="123" maxActive="50" maxIdle="30" maxWait="10000" /> </Context>
3.使用配置數(shù)據(jù)源的數(shù)據(jù)庫連接池時的數(shù)據(jù)庫操作工具類
代碼如下:
package db.utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.InitialContext;
import javax.sql.DataSource;
//import org.apache.log4j.Logger;
/**
* 數(shù)據(jù)庫操作輔助類
*/
public class DbUtils {
//private static Logger logger = Logger.getLogger("DbUtils");
/**
* 該語句必須是一個 SQL INSERT、UPDATE 或 DELETE 語句
* @param sql
* @param paramList:參數(shù),與SQL語句中的占位符一一對應(yīng)
* @return
* @throws Exception
*/
public int execute(String sql, List<Object> paramList) throws Exception {
if(sql == null || sql.trim().equals("")) {
//logger.info("parameter is valid!");
}
Connection conn = null;
PreparedStatement pstmt = null;
int result = 0;
try {
conn = getConnection();
pstmt = DbUtils.getPreparedStatement(conn, sql);
setPreparedStatementParam(pstmt, paramList);
if(pstmt == null) {
return -1;
}
result = pstmt.executeUpdate();
} catch (Exception e) {
//logger.info(e.getMessage());
throw new Exception(e);
} finally {
closeStatement(pstmt);
closeConn(conn);
}
return result;
}
/**
* 將查詢數(shù)據(jù)庫獲得的結(jié)果集轉(zhuǎn)換為Map對象
* @param sql:查詢語句
* @param paramList:參數(shù)
* @return
*/
public List<Map<String, Object>> getQueryList(String sql, List<Object> paramList) throws Exception {
if(sql == null || sql.trim().equals("")) {
//logger.info("parameter is valid!");
return null;
}
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Map<String, Object>> queryList = null;
try {
conn = getConnection();
pstmt = DbUtils.getPreparedStatement(conn, sql);
setPreparedStatementParam(pstmt, paramList);
if(pstmt == null) {
return null;
}
rs = getResultSet(pstmt);
queryList = getQueryList(rs);
} catch (RuntimeException e) {
//logger.info(e.getMessage());
System.out.println("parameter is valid!");
throw new Exception(e);
} finally {
closeResultSet(rs);
closeStatement(pstmt);
closeConn(conn);
}
return queryList;
}
private void setPreparedStatementParam(PreparedStatement pstmt, List<Object> paramList) throws Exception {
if(pstmt == null || paramList == null || paramList.isEmpty()) {
return;
}
DateFormat df = DateFormat.getDateTimeInstance();
for (int i = 0; i < paramList.size(); i++) {
if(paramList.get(i) instanceof Integer) {
int paramValue = ((Integer)paramList.get(i)).intValue();
pstmt.setInt(i+1, paramValue);
} else if(paramList.get(i) instanceof Float) {
float paramValue = ((Float)paramList.get(i)).floatValue();
pstmt.setFloat(i+1, paramValue);
} else if(paramList.get(i) instanceof Double) {
double paramValue = ((Double)paramList.get(i)).doubleValue();
pstmt.setDouble(i+1, paramValue);
} else if(paramList.get(i) instanceof Date) {
pstmt.setString(i+1, df.format((Date)paramList.get(i)));
} else if(paramList.get(i) instanceof Long) {
long paramValue = ((Long)paramList.get(i)).longValue();
pstmt.setLong(i+1, paramValue);
} else if(paramList.get(i) instanceof String) {
pstmt.setString(i+1, (String)paramList.get(i));
}
}
return;
}
/**
* 獲得數(shù)據(jù)庫連接
* @return
* @throws Exception
*/
private Connection getConnection() throws Exception {
InitialContext cxt = new InitialContext();
DataSource ds = (DataSource) cxt.lookup(jndiName);
if ( ds == null ) {
throw new Exception("Data source not found!");
}
return ds.getConnection();
}
private static PreparedStatement getPreparedStatement(Connection conn, String sql) throws Exception {
if(conn == null || sql == null || sql.trim().equals("")) {
return null;
}
PreparedStatement pstmt = conn.prepareStatement(sql.trim());
return pstmt;
}
/**
* 獲得數(shù)據(jù)庫查詢結(jié)果集
* @param pstmt
* @return
* @throws Exception
*/
private ResultSet getResultSet(PreparedStatement pstmt) throws Exception {
if(pstmt == null) {
return null;
}
ResultSet rs = pstmt.executeQuery();
return rs;
}
/**
* @param rs
* @return
* @throws Exception
*/
private List<Map<String, Object>> getQueryList(ResultSet rs) throws Exception {
if(rs == null) {
return null;
}
ResultSetMetaData rsMetaData = rs.getMetaData();
int columnCount = rsMetaData.getColumnCount();
List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
while (rs.next()) {
Map<String, Object> dataMap = new HashMap<String, Object>();
for (int i = 0; i < columnCount; i++) {
dataMap.put(rsMetaData.getColumnName(i+1), rs.getObject(i+1));
}
dataList.add(dataMap);
}
return dataList;
}
/**
* 關(guān)閉數(shù)據(jù)庫連接
* @param conn
*/
private void closeConn(Connection conn) {
if(conn == null) {
return;
}
try {
conn.close();
} catch (SQLException e) {
//logger.info(e.getMessage());
}
}
/**
* 關(guān)閉
* @param stmt
*/
private void closeStatement(Statement stmt) {
if(stmt == null) {
return;
}
try {
stmt.close();
} catch (SQLException e) {
//logger.info(e.getMessage());
}
}
/**
* 關(guān)閉
* @param rs
*/
private void closeResultSet(ResultSet rs) {
if(rs == null) {
return;
}
try {
rs.close();
} catch (SQLException e) {
//logger.info(e.getMessage());
}
}
private String jndiName = "java:/comp/env/jdbc/demoDB";
public void setJndiName(String jndiName) {
this.jndiName = jndiName;
}
}
總結(jié):使用配置數(shù)據(jù)源的方式連接數(shù)據(jù)庫,這種方式效率高且性能穩(wěn)定,推薦使用。
查看更多Java的語法,大家可以關(guān)注:《Thinking in Java 中文手冊》、《JDK 1.7 參考手冊官方英文版》、《JDK 1.6 API java 中文參考手冊》、《JDK 1.5 API java 中文參考手冊》,也希望大家多多支持腳本之家。
相關(guān)文章
java多線程之Future和FutureTask使用實(shí)例
這篇文章主要介紹了java多線程之Future和FutureTask使用實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
java遍歷http請求request的所有參數(shù)實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨ava遍歷http請求request的所有參數(shù)實(shí)現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09
jdbc+jsp實(shí)現(xiàn)簡單員工管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了jdbc+jsp實(shí)現(xiàn)簡單員工管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-02-02

