日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

连接池 DBCP c3p0以及分页的案例

發布時間:2024/8/24 编程问答 26 如意码农
生活随笔 收集整理的這篇文章主要介紹了 连接池 DBCP c3p0以及分页的案例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 連接池

思考:

程序中連接如何管理?

  1. 連接資源寶貴;需要對連接管理
  2. 連接:

a) 操作數據庫,創建連接

b) 操作結束,  關閉!

分析:

涉及頻繁的連接的打開、關閉,影響程序的運行效率!

連接管理:

預先創建一組連接,有的時候每次取出一個; 用完后,放回;

學習連接池:

  1. 自定義一個連接池
  2. 學習優秀的連接池組件

a) DBCP

b) C3P0

自定義連接池

代理:

如果對某個接口中的某個指定的方法的功能進行擴展,而不想實現接口里所有方法,可以使用(動態)代理模式!

Java中代理模式:靜態/動態/Cglib代理(spring)

使用動態代理,可以監測接口中方法的執行!

如何對Connection對象,生成一個代理對象:

|--Proxy

static Object newProxyInstance(

ClassLoader loader,    當前使用的類加載器

Class<?>[] interfaces,   目標對象(Connection)實現的接口類型

InvocationHandler h    事件處理器:當執行上面接口中的方法的時候,就會自動觸發事件處理器代碼,把當前執行的方法(method)作為參數傳入。

)  想要什么就努力的去得到,去想方設法,去行動,最終得到之。

說說代理Proxy這里到底干了什么,這里就是什么呢,可以使用pool.releaseConnection(conn)釋放鏈接,也可以鏈接本身直接conn.close()釋放鏈接,自身直接釋放鏈接的,不會改變pool中的屬性。Proxy的作用就是一種代理,是一種基于時間的機制,代理完成一些業務邏輯,當你執行某個方法,比如這里執行close方法的時候,我就要讓你順帶做一些改變pool屬性的一些邏輯。

/**

* 自定義連接池, 管理連接

* 代碼實現:

1.  MyPool.java  連接池類,

2.  指定全局參數:  初始化數目、最大連接數、當前連接、   連接池集合

3.  構造函數:循環創建3個連接

4.  寫一個創建連接的方法

5.  獲取連接

------>  判斷: 池中有連接, 直接拿

------>                池中沒有連接,

------>                 判斷,是否達到最大連接數; 達到,拋出異常;沒有達到最大連接數,

創建新的連接

6. 釋放連接

------->  連接放回集合中(..)

*

*/

public class MyPool {

private int init_count = 3; // 初始化連接數目

private int max_count = 6; // 最大連接數

private int current_count = 0;  // 記錄當前使用連接數

// 連接池 (存放所有的初始化連接)

private LinkedList<Connection> pool = new LinkedList<Connection>();

//1.  構造函數中,初始化連接放入連接池

public MyPool() {

// 初始化連接

for (int i=0; i<init_count; i++){

// 記錄當前連接數目

current_count++;

// 創建原始的連接對象

Connection con = createConnection();

// 把連接加入連接池

pool.addLast(con);

}

}

//2. 創建一個新的連接的方法

private Connection createConnection(){

try {

Class.forName("com.mysql.jdbc.Driver");

// 原始的目標對象

final Connection con = DriverManager.getConnection("jdbc:mysql:///jdbc_demo", "root", "root");

/**********對con對象代理**************/

// 對con創建其代理對象

Connection proxy = (Connection) Proxy.newProxyInstance(

con.getClass().getClassLoader(),    // 類加載器

//con.getClass().getInterfaces(),   // 當目標對象是一個具體的類的時候

new Class[]{Connection.class},      // 目標對象實現的接口

new InvocationHandler() { // 當調用con對象方法的時候, 自動觸發事務處理器

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

// 方法返回值

Object result = null;

// 當前執行的方法的方法名

String methodName = method.getName();

// 判斷當執行了close方法的時候,把連接放入連接池

if ("close".equals(methodName)) {

System.out.println("begin:當前執行close方法開始!");

// 連接放入連接池

pool.addLast(con);

System.out.println("end: 當前連接已經放入連接池了!");

} else {

// 調用目標對象方法

result = method.invoke(con, args);

}

return result;

}

}

);

return proxy;// 就是上面定義的 final Connection

} catch (Exception e) {

throw new RuntimeException(e);

}

}

//3. 獲取連接

public Connection getConnection(){

// 3.1 判斷連接池中是否有連接, 如果有連接,就直接從連接池取出

if (pool.size() > 0){

return pool.removeFirst();

}

// 3.2 連接池中沒有連接: 判斷,如果沒有達到最大連接數,創建;

if (current_count < max_count) {

// 記錄當前使用的連接數

current_count++;

// 創建連接

return createConnection();

}

// 3.3 如果當前已經達到最大連接數,拋出異常

throw new RuntimeException("當前連接已經達到最大連接數目 !");

}

//4. 釋放連接

public void realeaseConnection(Connection con) {

// 4.1 判斷: 池的數目如果小于初始化連接,就放入池中

if (pool.size() < init_count){

pool.addLast(con);

} else {

try {

// 4.2 關閉

current_count--;

con.close();

} catch (SQLException e) {

throw new RuntimeException(e);

}

}

}

public static void main(String[] args) throws SQLException {

MyPool pool = new MyPool();

System.out.println("當前連接: " + pool.current_count);  // 3

// 使用連接

pool.getConnection();

pool.getConnection();

Connection con4 = pool.getConnection();

Connection con3 = pool.getConnection();

Connection con2 = pool.getConnection();

Connection con1 = pool.getConnection();

// 釋放連接, 連接放回連接池

// pool.realeaseConnection(con1);

/*

* 希望:當關閉連接的時候,要把連接放入連接池!【當調用Connection接口的close方法時候,希望觸發pool.addLast(con);操作】

* 把連接放入連接池

* 解決1:實現Connection接口,重寫close方法

* 解決2:動態代理

*/

con1.close();

// 再獲取

pool.getConnection();

System.out.println("連接池:" + pool.pool.size());      // 0

System.out.println("當前連接: " + pool.current_count);  // 3

}

}

代理的總結:(了解會用)

使用代理,可以在不實現接口的情況,對接口的方法進行擴展,添加額外的用戶需要的業務邏輯!

2.開源的連接池技術

概述:

Sun公司約定: 如果是連接池技術,需要實現一個接口!

javax.sql.DataSource;

連接池:

DBCP

C3P0

2.1 DBCP連接池:

l DBCP 是 Apache 軟件基金組織下的開源連接池實現,使用DBCP數據源,應用程序應在系統中增加如下兩個 jar 文件:

  • Commons-dbcp.jar:連接池的實現
  • Commons-pool.jar:連接池實現的依賴庫

l Tomcat 的連接池正是采用該連接池來實現的。該數據庫連接池既可以與應用服務器整合使用,也可由應用程序獨立使用。

l 核心類:BasicDataSource、BasicDataSourceFactory

l 使用步驟

  • 引入jar文件

l commons-dbcp-1.4.jar

l commons-pool-1.5.6.jar

public class App_DBCP {

// 1. 硬編碼方式實現連接池

@Test

public void testDbcp() throws Exception {

// DBCP連接池核心類

BasicDataSource dataSouce = new BasicDataSource();

// 連接池參數配置:初始化連接數、最大連接數 / 連接字符串、驅動、用戶、密碼

dataSouce.setUrl("jdbc:mysql:///jdbc_demo"); //數據庫連接字符串

dataSouce.setDriverClassName("com.mysql.jdbc.Driver");  //數據庫驅動

dataSouce.setUsername("root"); //數據庫連接用戶

dataSouce.setPassword("root"); //數據庫連接密碼

dataSouce.setInitialSize(3);  // 初始化連接

dataSouce.setMaxActive(6);   // 最大連接

dataSouce.setMaxIdle(3000);   // 最大空閑時間

// 獲取連接

Connection con = dataSouce.getConnection();

con.prepareStatement("delete from admin where id=3").executeUpdate();

// 關閉

con.close();

}

@Test

// 2. 【推薦】配置方式實現連接池  ,  便于維護

public void testProp() throws Exception {

// 加載prop配置文件

Properties prop = new Properties();

// 獲取文件流

InputStream inStream = App_DBCP.class.getResourceAsStream("db.properties");

// 加載屬性配置文件

prop.load(inStream);

// 根據prop配置,直接創建數據源對象

DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);

// 獲取連接

Connection con = dataSouce.getConnection();

con.prepareStatement("delete from admin where id=4").executeUpdate();

// 關閉

con.close();

}

}

配置方式實現DBCP連接池,  配置文件中的key與BaseDataSouce中的屬性一樣:

db.properties

url=jdbc:mysql:///jdbc_demo

driverClassName=com.mysql.jdbc.Driver

username=root

password=root

initialSize=3

maxActive=6

maxIdle=3000

注意:這里App_DBCP.class.getResourceAsInputstrem(“/db.properties”);路徑的寫法

帶 / 表示工程的根目錄

不帶/ 表示該類所在的目錄

都是這樣的,/都是表示根

配置文件,一般使用xml和properties文件存儲,前者使用的更為廣泛,后者這是做一些簡單的數據存儲。凡是有關系的尤其是包含關系的,一定是使用xml文件存儲。Properties本事就是一個map影視而已,當然存儲的都是鍵值對。

2.2 C3P0連接池:

C3P0連接池:

最常用的連接池技術!Spring框架,默認支持C3P0連接池技術!

C3P0連接池,核心類:

CombopooledDataSource ds;通過查看源碼,可以發現這個類,也是實現了sun定義DataSource接口的。

使用:

  1. 下載,引入jar文件:  c3p0-0.9.1.2.jar
  2. 使用連接池,創建連接

a) 硬編碼方式

b) 配置方式(xml),這個xml的模板必須從c3p0的源碼包中拷貝出來,不用更改xml文件的名稱,只需要修改xml文件中的內容即可。創建ComboPooleDataSource對象的時候將會自動加載這個xml配置文件。

Ctrl + shift + \取消注釋,只需要保留<default-config>即可,別的都可以刪除

public class App {

@Test

//1. 硬編碼方式,使用C3P0連接池管理連接

public void testCode() throws Exception {

// 創建連接池核心工具類

ComboPooledDataSource dataSource = new ComboPooledDataSource();

// 設置連接參數:url、驅動、用戶密碼、初始連接數、最大連接數

dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo");

dataSource.setDriverClass("com.mysql.jdbc.Driver");

dataSource.setUser("root");

dataSource.setPassword("root");

dataSource.setInitialPoolSize(3);

dataSource.setMaxPoolSize(6);

dataSource.setMaxIdleTime(1000);

// ---> 從連接池對象中,獲取連接對象

Connection con = dataSource.getConnection();

// 執行更新

con.prepareStatement("delete from admin where id=7").executeUpdate();

// 關閉

con.close();

}

@Test

//2. XML配置方式,使用C3P0連接池管理連接

public void testXML() throws Exception {

// 創建c3p0連接池核心工具類

// 自動加載src下c3p0的配置文件【c3p0-config.xml】

ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默認的配置

// 獲取連接

Connection con = dataSource.getConnection();

// 執行更新

con.prepareStatement("delete from admin where id=5").executeUpdate();

// 關閉

con.close();

}

}

2.3 優化

項目,連接的管理,交給連接池!

還是之前的項目:

public class JdbcUtil {

private static ComboPooledDataSource dataSource = null;

/**

* 靜態代碼塊準備需要的一些數據

*/

static

{

dataSource = new ComboPooledDataSource();

}

/**

* 建立數據庫鏈接的操作

*/

public static Connection getConnection()

{

try {

return dataSource.getConnection();

} catch (SQLException e) {

throw new RuntimeException(e);

}

}

/**

* 關閉數據庫鏈接

* @param conn

* @param stmt

* @param rs

*/

public static void closeAll(Connection conn, Statement stmt, ResultSet rs)

{

if(rs!=null)

{

try {

rs.close();

rs = null;

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

if(stmt!=null)

{

try {

stmt.close();

stmt = null;

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

if(conn!=null)

{

try {

conn.close();

conn = null;

} catch (Exception e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

}

}

3. 分頁技術

分頁技術:

JSP頁面,用來顯示數據! 如果數據有1000條,分頁顯示,每頁顯示10條,共100頁;   好處:  利于頁面布局,且顯示的效率高!

分頁關鍵點:

  1. 分頁SQL語句;
  2. 后臺處理: dao/service/servlet/JSP

分頁的sql語句:

第一個參數:當前頁的其實索引行 = (當前頁數 - 1)*每頁顯示的條目數

第二個參數:每頁顯示的條目數

Select * from employee limit 0, 4;

實現步驟:

  1. 環境準備

a) 引入jar文件及引入配置文件

  1. 數據庫驅動包
  2. C3P0連接池jar文件 及 配置文件
  3. DbUtis組件:    QueryRunner qr = new QueryRuner(dataSouce);

qr.update(sql);

b) 公用類: JdbcUtils.java

  1. 先設計:PageBean.java
  2. Dao接口設計/實現:   2個方法
  3. Service/servlet
  4. JSP

作業:

需求:自擬

要求功能:

  1. 列表展示、分頁 【必須有】
  2. 注冊、登陸

a) 登陸后,進入第1步驟的列表頁面(分頁)

b) 注冊成功,跳轉到登陸頁面,讓用戶登陸

  1. 擴展

a) 對列表數據修改

b) 對列表數據刪除

c) 新增數據

PageBean的設計

public class PageBean <T> {

private int currentPage = 1; //當前顯示的頁面 默認顯示第一頁

private int pageCount = 4; //查詢返回的條數 默認 每頁4條數據

private int totalCount; //總記錄數

private int totalPage; //總頁數

private List<T> pageData; //分頁查詢到的數據

public int getCurrentPage() {

return currentPage;

}

public void setCurrentPage(int currentPage) {

this.currentPage = currentPage;

}

public int getPageCount() {

return pageCount;

}

public void setPageCount(int pageCount) {

this.pageCount = pageCount;

}

public int getTotalCount() {

return totalCount;

}

public void setTotalCount(int totalCount) {

this.totalCount = totalCount;

}

public int getTotalPage() {

if(totalCount % pageCount == 0)

{

totalPage = totalCount / pageCount;

}

else

{

totalPage = totalCount / pageCount + 1;

}

return totalPage;

}

public void setTotalPage(int totalPage) {

this.totalPage = totalPage;

}

public List<T> getPageData() {

return pageData;

}

public void setPageData(List<T> pageData) {

this.pageData = pageData;

}

}

分頁項目總的jdbcutil使用了c3p0包和DbUtils包

C3p0是干啥的:創立連接池,從連接池中獲取鏈接的。

DbUtils是干啥的:dbutils下面主要是有兩個類,一個DbUtils類主要是用來實現數據庫的連接的,QueryRunner主要是用來實現執行sql語句的(往往這是我們使用DBUtils的主要內容)

通常是c3p0和DbUtil搭配使用,前者用來獲取連接,后者用來放回一個QueryRunner用來執行sql語句。

public class JdbcUtil {

private static ComboPooledDataSource dataSource = null;

// 初始化

static {

// 一旦創建 建輝默認的加載 c3p0文件

dataSource = new ComboPooledDataSource();

}

// 創建DbUtils核心工具類對象

public static QueryRunner getQueryRunner()

{

// 創建 QueryRunner的時候 可以傳入一參數 datasource 這樣在 執行 qr.executeUpdate()的

//時候 尅不傳入鏈接,這樣最終也不需要 手動的 conn.close()

return new QueryRunner(dataSource);// 看到沒有這里都不需要getConnection的操作,所以我們后面也不需要自己師范conn,stmt,rs等資源

}

// 當然有可能有某些函數中還需要使用connection所以可以寫一個getConnection

// 獲取連接 一遍那些需要使用 數據庫鏈接的地方使用

public static Connection getConnection()

{

try {

return dataSource.getConnection();// 從連接池中 拿出一個鏈接來

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

throw new RuntimeException(e);

}

}

}

<a href="${pageContext.request.contextPath }/index?currentPage=1">首頁</a>這里再說一下,pageContext是jsp中的內置對象,失眠是在EL表達式中使用了內置對象。EL表達式中,使用get方法時只寫get后面的名字就可以了。

一般jsp、html等資源都是給瀏覽器使用。如果使用轉發時,應當寫上完整的路徑,如下:

String uri = “/error/error.jsp”; //這個時候第一個/表示的就是項目根目錄和request.getContextPath()是一樣的。

reqeust.getRequestDispacher(uri).forward(request, response);

如果使用重定向的話如下:

response.sendRedirect(request.getContextPath() + “/error/error.jsp”);

Servlet動態資源,編譯之后,request.getContextPath/class里面,一般servlet資源找給服務器使用,這個時候一般使用的都是重定向request.getRequestDispacher(“/IndexServlet”),直接重定向過去,這個時候,IndexServlet前面的 / 就相當于request.getContextPath

總結

以上是生活随笔為你收集整理的连接池 DBCP c3p0以及分页的案例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。