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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

01_数据库连接池,数据源,ResultSetMetaData,jdbc优化

發布時間:2024/9/27 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 01_数据库连接池,数据源,ResultSetMetaData,jdbc优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


一、數據庫連接池

1. 什么是連接池

傳統的開發模式下,Servlet處理用戶的請求,找Dao查詢數據,dao會創建與數據庫之間的連接,完成數據查詢后會關閉數據庫的鏈接。

這樣的方式會導致用戶每次請求都要向數據庫建立鏈接而數據庫創建連接通常需要消耗相對較大的資源,創建時間也較長。假設網站一天10萬訪問量,數據庫服務器就需要創建10萬次連接,極大的浪費數據庫的資源,并且極易造成數據庫服務器內存溢出、宕機。

?

解決方案就是數據庫連接池

連接池就是數據庫連接對象的一個緩沖池

我們可以先創建10個數據庫連接緩存在連接池中,當用戶有請求過來的時候,dao不必創建數據庫連接,而是從數據庫連接池中獲取一個,用完了也不必關閉連接,而是將連接換回池子當中,繼續緩存

?

使用數據庫連接池可以極大地提高系統的性能

?

2. 實現數據庫連接池

jdbc統一了數據庫的操作? 定義了規范

jdbc針對數據庫連接池也定義的接口java.sql.DataSource,所有的數據庫連接池實現都要實現該接口

該接口中定義了兩個重載的方法

Connection getConnection()

Connection getConnection(String?username,String?password)

?

數據庫連接池實現思路

1定義一個類實現java.sql.DataSource接口

2定義一個集合用于保存Connection對象,由于頻繁地增刪操作,用LinkedList比較好

3實現getConnection方法,在方法中取出LinkedList集合中的一個連接對象返回

注意:

??? 返回的Connection對象不是從集合中獲得,而是刪除

??? 用戶用完Connection,會調用close方法釋放資源,此時要保證連接換回連接池,而不是關閉連接

??? 重寫close方法是難點,解決方案:裝飾設計模式、動態代理

?

二、 數據源

通常我們把DataSource的實現,按其英文含義稱之為數據源,數據源中都包含了數據庫連接池的實現。

?

一些開源組織提供了數據源的獨立實現,常用的有:

DBCP 數據庫連接池

C3P0 數據庫連接池

1.? DBCP 數據源

介紹

DBCP Apache 軟件基金組織下的開源連接池實現

tomcat服務器就是使用DBCP作為數據庫連接池

使用DBCP數據源,需要導入兩個jar

Commons-dbcp.jar:連接池的實現

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

?

DBCP核心 API

BasicDataSource

數據源實現

BasicDataSourceFactory

用于創建數據源的工廠類

?

dbcp 創建連接池

方法1?直接創建對象,設置參數

BasicDataSource bds = new BasicDataSource();

?

// 設置連接數據庫需要的配置信息

bds.setDriverClassName("com.mysql.jdbc.Driver");

bds.setUrl("jdbc:mysql://localhost:3306/jdbc3");

bds.setUsername("root");

bds.setPassword("root");

?

// 設置連接池的參數

bds.setInitialSize(5);

bds.setMaxActive(10);

?

ds = bds

?

方法2 通過工廠類創建對象,讀取配置文件

try {

?? Properties prop =new Properties();

?? // 讀配置文件

?? InputStream in =

?? JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");

?? prop.load(in);

?? ds =BasicDataSourceFactory.createDataSource(prop);

}catch (Exception e) {

?? throw newExceptionInInitializerError(e);

}

?

配置文件為dbcpconfig.properties

#連接設置

driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/jdbc3

username=root

password=root

?

#<!-- 初始化連接 -->

initialSize=5

?

#最大連接數量

maxActive=10

?

#<!-- 最大空閑連接 -->

maxIdle=10

?

?

#<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等于60 -->

maxWait=60000

?

?

#JDBC驅動建立連接時附帶的連接屬性屬性的格式必須為這樣:[屬性名=property;]

#注意:"user" "password" 兩個屬性會被明確地傳遞,因此這里不需要包含他們。

connectionProperties=useUnicode=true;characterEncoding=gbk

?

#指定由連接池所創建的連接的自動提交(auto-commit)狀態。

defaultAutoCommit=true

?

#driver default 指定由連接池所創建的連接的只讀(read-only)狀態。

#如果沒有設置該值,則“setReadOnly”方法將不被調用。(某些驅動并不支持只讀模式,如:Informix

defaultReadOnly=

?

#driver default 指定由連接池所創建的連接的事務級別(TransactionIsolation)。

#可用值為下列之一:(詳情可見javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED,REPEATABLE_READ, SERIALIZABLE

defaultTransactionIsolation=READ_UNCOMMITTED

2.? C3P0 數據源

介紹

c3p0是一個開源的jdbc連接池,我們熟悉的Hibernate Spring 框架使用的都是該數據源

?

創建連接池對象

方法1:直接創建對象,設置參數

ComboPooledDataSource cpds = new ComboPooledDataSource();

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

cpds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc3");

cpds.setUser("root");

cpds.setPassword("root");

cpds.setInitialPoolSize(5);

cpds.setMaxPoolSize(15);

方法2:讀取配置文件

ComboPooledDataSource cpds = newComboPooledDataSource("itcast");

配置文件為c3p0-config.xml 該文件需要放在類路徑下

<c3p0-config>

?

?? <default-config>

?? ?? <!—- 默認配置 –->

????? <propertyname="initialPoolSize">5</property>

????? <propertyname="maxPoolSize">15</property>

????? <propertyname="driverClass">com.mysql.jdbc.Driver</property>

????? <propertyname="jdbcUrl">jdbc:mysql://localhost:3306/jdbc3</property>

????? <propertyname="user">root</property>

????? <propertyname="password">root</property>

?? </default-config>

?? <named-configname="xwh">

????? <propertyname="initialPoolSize">5</property>

????? <propertyname="maxPoolSize">15</property>

????? <propertyname="driverClass">com.mysql.jdbc.Driver</property>

????? <propertyname="jdbcUrl">jdbc:mysql://localhost:3306/jdbc3</property>

????? <propertyname="user">root</property>

????? <propertyname="password">root</property>

?? </named-config>

</c3p0-config>

?

三、ResultSetMetaData對象

元數據,可以理解為描述數據的數據

jdbc中的元數據是指數據庫、表、列的定義信息

?

ResultSetMetaData對象表示結果集 ResultSet對象的元數據

獲得該對象:

ResultSetMetaDatametaData = rs.getMetaData();

?

常用方法:

getColumnCount() ?返回resultset對象的列數

getColumnName(int?column) ?獲得指定列的名稱

getColumnTypeName(int?column) 獲得指定列的類型

?

四、jdbc優化

使用jdbc對數據庫進行crud操作時,會有很多重復的代碼,仔細分析不難發現其實變化的只是其中幾行代碼

?

對于 cud(增刪改) 操作,代碼幾乎完全一樣, 唯一的區別就是sql語句不同,我們完全可以把相同的代碼抽取出來定義在一個工具方法中,然后定義一個參數來接收sql語句

?

對于 r(查詢) 操作,除SQL語句不同之外,根據操作的實體不同,對ResultSet結果集的處理也有所不相同,因此可義一個query方法,除以參數形式接收變化的SQL語句外,可以使用策略模式由qurey方法的調用者決定如何把ResultSet中的數據映射到實體對象中

?

優化后的工具類 JdbcUtils

// 通用的增刪改方法

public static int update(String sql, Object[] params) throws SQLException {

?? Connection conn =null;

?? PreparedStatementpstmt = null;

?? ResultSet rs = null;

?? try {

????? // 獲得連接

????? conn =getConnection();

????? // 預編譯sql

????? pstmt =conn.prepareStatement(sql);

????? // 將參數設置進去

????? for(int i=0;?params!=null&&i<params.length; i++) {

???????? pstmt.setObject(i+1,params[i]);

????? }

????? // 發送sql

????? int num = pstmt.executeUpdate();

????? return num;

?? } finally {

????? // 釋放資源

????? release(conn,pstmt, rs);

?? }

}

?

// 優化查詢

public static Object query(String sql, Object[] params,ResultSetHandler rsh) throws SQLException {

?? Connection conn =null;

?? PreparedStatementpstmt = null;

?? ResultSet rs = null;

?? try {

????? // 獲得連接

????? conn =getConnection();

????? // 預編譯sql

????? pstmt =conn.prepareStatement(sql);

????? // 將參數設置進去

????? for(int i=0; params!=null&&i<params.length;i++) {

???????? pstmt.setObject(i+1,params[i]);

????? }

????? // 發送sql

????? rs =pstmt.executeQuery();

????? // 不知道別人想如何處理結果集

????? // 干脆想別人所要一個結果集的處理器

????? // 為了讓當前代碼繼續,定義一個結果集處理器接口

????? // 策略模式, 規定算法,具體的算法留給將來的調用者實現

????? Object obj =rsh.handle(rs);

????? return obj;

?? } finally {

????? // 釋放資源

????? release(conn,pstmt, rs);

?? }

}

?

?

結果集處理器接口

public interface ResultSetHandler {

?? // 處理結果集的方法

?? public Objecthandle(ResultSet rs);

}

?

實現類:

BeanListHandler

public class BeanListHandler implements ResultSetHandler{

?

?? private Classclazz;

?? publicBeanListHandler(Class clazz) {

????? this.clazz =clazz;

?? }

?? public Objecthandle(ResultSet rs) {

????? try {

???????? // 取出結果集所有的記錄,封裝到bean,存入list返回

???????? List list =new ArrayList();

???????? while(rs.next()) {

??????????? Objectbean = clazz.newInstance();

??????????? // 獲得元數據

??????????? ResultSetMetaDatametaData = rs.getMetaData();

??????????? // 獲得列的數量

??????????? intcount = metaData.getColumnCount();

??????????? // 遍歷列

??????????? for(inti=1; i<=count; i++) {

??????????????? // 取列名

??????????????? StringcolumnName = metaData.getColumnName(i);

??????????????? // 取這列的值

??????????????? Objectvalue = rs.getObject(columnName);

??????????????? // 反射出屬性

??????????????? Fieldfield = clazz.getDeclaredField(columnName);

??????????????? // 設置屬性

??????????????? field.setAccessible(true);

??????????????? field.set(bean,value);

??????????? }

??????????? // 加入list

??????????? list.add(bean);

???????? }

???????? returnlist;

????? } catch(Exception e) {

???????? throw newRuntimeException(e);

????? }

?? }

?

}

?

BeanHandler

public class BeanHandler implements ResultSetHandler {

?? private Classclazz;

?? publicBeanHandler(Class clazz) {

????? this.clazz =clazz;

?? }

?? public Objecthandle(ResultSet rs) {

????? // 不知道有幾列數據,不知道列名,不知道封裝到什么樣的bean

????? // 表的列明和javabean的字段名一致

????? try {

???????? if(rs.next()){

??????????? // 創建bean

??????????? Objectbean = clazz.newInstance();

??????????? // 封裝數據

??????????? // 獲得結果集的元數據

??????????? ResultSetMetaDatametaData = rs.getMetaData();

??????????? intcount = metaData.getColumnCount();

??????????? // 迭代取每一列的數據

??????????? for(inti=1; i<=count; i++) {

??????????????? // 獲得列名? username

??????????????? StringcolumnName = metaData.getColumnName(i);

??????????????? // 獲得數據ddd

??????????????? Objectvalue = rs.getObject(columnName);

??????????????? // 根據列名反射出映射的屬性 username

??????????????? Fieldfield = clazz.getDeclaredField(columnName);

??????????????? // 為屬性賦值

??????????????? field.setAccessible(true);

??????????????? field.set(bean,value);

??????????? }

??????????? returnbean;

???????? }

???????? return null;

????? } catch(Exception e) {

???????? throw newRuntimeException(e);

????? }

?? }

?

}

?

ArrayHandler

// 取出第一行的所有記錄存入一個Object數組

public class ArrayHandler implements ResultSetHandler {

?

?? public Objecthandle(ResultSet rs) {

????? try {

???????? if(rs.next()) {

??????????? // 指向了第一行的記錄

??????????? // 獲得元數據

??????????? ResultSetMetaDatametaData = rs.getMetaData();

??????????? // 獲得列數

??????????? intcount = metaData.getColumnCount();

??????????? // 創建數組

??????????? Object[]arr = new Object[count];

??????????? // 迭代所有列的值,存入數組

??????????? for(inti=1; i<=count; i++) {

??????????????? Objectvalue = rs.getObject(i); // 獲得指定列的值

??????????????? arr[i-1]= value;

??????????? }

??????????? returnarr;

???????? }

???????? return null;

????? } catch(Exception e) {

???????? throw newRuntimeException(e);

????? }

?? }

}

?

批處理

?

處理大數據

Clob Character large Object

text

?

Blob binary?large object

總結

以上是生活随笔為你收集整理的01_数据库连接池,数据源,ResultSetMetaData,jdbc优化的全部內容,希望文章能夠幫你解決所遇到的問題。

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