1. 程式人生 > >網絡協議 finally{ return問題 註入問題 jdbc註冊驅動問題 PreparedStatement 連接池目的 1.2.1DBCP連接池 C3P0連接池 MYSQL兩種方式進行實物管理 JDBC事務 DBUtils事務 ThreadLocal 事務特性 並發訪問 隔離級別

網絡協議 finally{ return問題 註入問題 jdbc註冊驅動問題 PreparedStatement 連接池目的 1.2.1DBCP連接池 C3P0連接池 MYSQL兩種方式進行實物管理 JDBC事務 DBUtils事務 ThreadLocal 事務特性 並發訪問 隔離級別

ID -- 1.7 ner red style 沒有 建立 工具

1.1.1 API詳解:註冊驅動

DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建議使用

原因有2個:

>導致驅動被註冊2次。

>強烈依賴數據庫的驅動jar

解決辦法:

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

1.1.2 API詳解:java.sql.Statement接口: 操作sql語句,並返回相應結果

String sql = "SQL語句";

獲取Statement語句執行平臺:Statement stmt = con.createStatement();

常用方法:

n int executeUpdate(String sql); --執行insert update delete語句.

n ResultSet executeQuery(String sql); --執行select語句.

n boolean execute(String sql); --僅當執行select並且有結果時才返回true,執行其他的語句返回false.

1.1.3 API詳解:處理結果集(註:執行insertupdatedelete無需處理)

ResultSet實際上就是一張二維的表格,我們可以調用其boolean next()方法指向某行記錄,當第一次調用next()方法時,便指向第一行記錄的位置,這時就可以使用

ResultSet提供的getXXX(int col)方法(與索引從0開始不同個,列從1開始)來獲取指定列的數據:

rs.next();//指向第一行

rs.getInt(1);//獲取第一行第一列的數據

常用方法:

n Object getObject(int index) / Object getObject(String name) 獲得任意對象

n String getString(int index)/ String getString(String name) 獲得字符串

n int getInt(int index)/int getInt(String name) 獲得整形

n double getDouble(int index)/ double getDouble(String name) 獲得雙精度浮點型

1.1.4 SQL註入問題

SQL註入:用戶輸入的內容作為了SQL語句語法的一部分,改變了原有SQL真正的意義。

假設有登錄案例SQL語句如下:

SELECT * FROM 用戶表 WHERE NAME = 用戶輸入的用戶名 AND PASSWORD = 用戶輸的密碼;

此時,當用戶輸入正確的賬號與密碼後,查詢到了信息則讓用戶登錄。但是當用戶輸入的賬號為XXX 密碼為:XXX’ OR ‘a’=’a時,則真正執行的代碼變為:

SELECT * FROM 用戶表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;

此時,上述查詢語句時永遠可以查詢出結果的。那麽用戶就直接登錄成功了,顯然我們不希望看到這樣的結果,這便是SQL註入問題。

為此,我們使用PreparedStatement來解決對應的問題。

preparedStatement:預編譯對象,是Statement對象的子類。

特點:

性能高

會把sql語句先編譯

能過濾掉用戶輸入的關鍵字。

PreparedStatement處理對象,處理的每條sql語句中所有的實際參數,都必須使用占位符?替換。

1.連接池目的:解決建立數據庫連接耗費資源和時間很多的問題,提高性能。

常見的連接池:DBCPC3P0

1.1 常用的數據源配置

1.1.1 DBCP連接池

DBCPApache推出的Database Connection Pool

使用步驟:

> 添加jarcommons-dbcp-1.4.jar commons-pool-1.5.6.jar

> 添加屬性資源文件

l 配置文件名稱:*.properties

l 配置文件位置:任意,建議srcclasspath/類路徑)

l 配置文件內容:properties不能編寫中文

> 編寫數據源工具類

1.1.2 C3P0連接池

C3P0開源免費的連接池!目前使用它的開源項目有:SpringHibernate等。使用第三方工具需要導入jar包,c3p0使用時還需要添加配置文件 c3p0-config.xml

使用步驟:

1、添加jar

2、編寫配置文件

c3p0-config.xml,放在src中(註:文件名一定不要寫錯)

技術分享圖片

3、編寫工具類:

技術分享圖片

技術分享圖片

1.1.3 概述

DBUtilsjava編程中的數據庫操作實用工具,小巧簡單實用。

DBUtils封裝了對JDBC的操作,簡化了JDBC操作,可以少寫代碼。

Dbutils三個核心功能介紹

l QueryRunner中提供對sql語句操作的API.

l ResultSetHandler接口,用於定義select操作後,怎樣封裝結果集.

l DbUtils類,它就是一個工具類,定義了關閉資源與事務處理的方法

1.1.4 QueryRunner核心類

l QueryRunner(DataSource ds) ,提供數據源(連接池),DBUtils底層自動維護連接connection

l update(String sql, Object... params) ,執行更新數據 insert update delete

1.1.5 qResultSetHandler結果集處理類

ArrayHandler

將結果集中的第一條記錄封裝到一個Object[]數組中,數組中的每一個元素就是這條記錄中的每一個字段的值

ArrayListHandler

將結果集中的每一條記錄都封裝到一個Object[]數組中,將這些數組在封裝到List集合中。

BeanHandler

將結果集中第一條記錄封裝到一個指定的javaBean中。

BeanListHandler

將結果集中每一條記錄封裝到指定的javaBean中,將這些javaBean在封裝到List集合中

ColumnListHandler

將結果集中指定的列的字段值,封裝到一個List集合中

KeyedHandler

將結果集中每一條記錄封裝到Map<String,Object>,在將這個map集合做為另一個Mapvalue,另一個Map集合的key是指定的字段的值。

MapHandler

將結果集中第一條記錄封裝到了Map<String,Object>集合中,key就是字段名稱,value就是字段值

MapListHandler

將結果集中每一條記錄封裝到了Map<String,Object>集合中,key就是字段名稱,value就是字段值,在將這些Map封裝到List集合中。

ScalarHandler

它是用於單個數據。例如select count(*) from 表操作。

l Query(String sql, ResultSetHandler<T> rsh, Object... params) ,執行查詢 select

l 事務指的是邏輯上的一組操作,組成這組操作的各個單元要麽全都成功,要麽全都失敗.

l 操作:

n MYSQL中可以有兩種方式進行事務的管理:

u 自動提交:MySql默認自動提交。及執行一條sql語句提交一次事務。

u 手動提交:先開啟,再提交

n 方式1:手動提交

start transaction;

update account set money=money-1000 where name=‘jack‘;

update account set money=money+1000 where name=‘rose‘;

commit;

#或者

rollback;

n 方式2:自動提交,通過修改mysql全局變量“autocommit”進行控制

show variables like ‘%commit%‘;

技術分享圖片

* 設置自動提交的參數為OFF:

set autocommit = 0; -- 0:OFF 1:ON

l 擴展:Oracle數據庫事務不自動提交

1.1.6 JDBC事務操作

Connection對象的方法名

描述

conn.setAutoCommit(false)

開啟事務

conn.commit()

提交事務

conn.rollback()

回滾事務

//事務模板代碼

public void demo01() throws SQLException{

// 獲得連接

Connection conn = null;

try {

//#1 開始事務

conn.setAutoCommit(false);

//.... 加錢 ,減錢

//#2 提交事務

conn.commit();

} catch (Exception e) {

//#3 回滾事務

conn.rollback();

} finally{

// 釋放資源

conn.close();

}

}

如果發生異常了, service被捕捉了 servlet層發現不了異常了, 需要從service

Throw new runtimeException(“”) 把異常拋給servlet

1.1.7 DBUtils事務操作

Connection對象的方法名

描述

conn.setAutoCommit(false)

開啟事務

new QueryRunner()

創建核心類,不設置數據源(手動管理連接)

query(conn , sql , handler, params )

update(conn, sql , params)

手動傳遞連接

DbUtils.commitAndClose(conn)

DbUtils.rollbackAndClose(conn)

提交並關閉連接

回滾並關閉連接

1.1.8 相關知識:ThreadLocal

java.lang.ThreadLocal 該類提供了線程局部 (thread-local) 變量,用於在當前線程中共享數據。

技術分享圖片

1.1.9 分析

1.1.10 事務特性:ACID

l 原子性(Atomicity)原子性是指事務是一個不可分割的工作單位,事務中的操作要麽都發生,要麽都不發生。

l 一致性(Consistency)事務前後數據的完整性必須保持一致。

l 隔離性(Isolation)事務的隔離性是指多個用戶並發訪問數據庫時,一個用戶的事務不能被其它用戶的事務所幹擾,多個並發事務之間數據要相互隔離。

l 持久性(Durability)持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響。

1.1.11 並發訪問問題

如果不考慮隔離性,事務存在3中並發訪問問題。

  1. 臟讀:一個事務讀到了另一個事務未提交的數據.
  2. 不可重復讀:一個事務讀到了另一個事務已經提交(update)的數據。引發另一個事務,在事務中的多次查詢結果不一致。
  3. 虛讀 /幻讀:一個事務讀到了另一個事務已經提交(insert)的數據。導致另一個事務,在事務中多次查詢的結果不一致。

1.1.12 隔離級別:解決問題

l 數據庫規範規定了4種隔離級別,分別用於描述兩個事務並發的所有情況。

  1. read uncommitted 讀未提交,一個事務讀到另一個事務沒有提交的數據。

a) 存在3個問題(臟讀、不可重復讀、虛讀)。

b) 解決:0個問題

  1. read committed 讀已提交,一個事務讀到另一個事務已經提交的數據。

a) 存在2個問題(不可重復讀、虛讀)。

b) 解決:1個問題(臟讀)

  1. repeatable read :可重復讀,在一個事務中讀到的數據始終保持一致,無論另一個事務是否提交。

a) 存在1個問題(虛讀)。

b) 解決:2個問題(臟讀、不可重復讀)

  1. serializable 串行化,同時只能執行一個事務,相當於事務中的單線程。

a) 存在0個問題。

b) 解決:3個問題(臟讀、不可重復讀、虛讀)

l 安全和性能對比

n 安全性:serializable > repeatable read > read committed > read uncommitted

n 性能 serializable < repeatable read < read committed < read uncommitted

l 常見數據庫的默認隔離級別:

n MySqlrepeatable read

n Oracle:read committed

網絡協議 finally{ return問題 註入問題 jdbc註冊驅動問題 PreparedStatement 連接池目的 1.2.1DBCP連接池 C3P0連接池 MYSQL兩種方式進行實物管理 JDBC事務 DBUtils事務 ThreadLocal 事務特性 並發訪問 隔離級別