網絡協議 finally{ return問題 註入問題 jdbc註冊驅動問題 PreparedStatement 連接池目的 1.2.1DBCP連接池 C3P0連接池 MYSQL兩種方式進行實物管理 JDBC事務 DBUtils事務 ThreadLocal 事務特性 並發訪問 隔離級別
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詳解:處理結果集(註:執行insert、update、delete無需處理)
ResultSet實際上就是一張二維的表格,我們可以調用其boolean next()方法指向某行記錄,當第一次調用next()方法時,便指向第一行記錄的位置,這時就可以使用
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.連接池目的:解決建立數據庫連接耗費資源和時間很多的問題,提高性能。
常見的連接池:DBCP、C3P0。
1.1 常用的數據源配置
1.1.1 DBCP連接池
DBCP:Apache推出的Database Connection Pool
使用步驟:
> 添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
> 添加屬性資源文件
l 配置文件名稱:*.properties
l 配置文件位置:任意,建議src(classpath/類路徑)
l 配置文件內容:properties不能編寫中文
> 編寫數據源工具類
1.1.2 C3P0連接池
C3P0開源免費的連接池!目前使用它的開源項目有:Spring、Hibernate等。使用第三方工具需要導入jar包,c3p0使用時還需要添加配置文件 c3p0-config.xml
使用步驟:
1、添加jar包
2、編寫配置文件
c3p0-config.xml,放在src中(註:文件名一定不要寫錯)
3、編寫工具類:
1.1.3 概述
DBUtils是java編程中的數據庫操作實用工具,小巧簡單實用。
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集合做為另一個Map的value,另一個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中並發訪問問題。
- 臟讀:一個事務讀到了另一個事務未提交的數據.
- 不可重復讀:一個事務讀到了另一個事務已經提交(update)的數據。引發另一個事務,在事務中的多次查詢結果不一致。
- 虛讀 /幻讀:一個事務讀到了另一個事務已經提交(insert)的數據。導致另一個事務,在事務中多次查詢的結果不一致。
1.1.12 隔離級別:解決問題
l 數據庫規範規定了4種隔離級別,分別用於描述兩個事務並發的所有情況。
- read uncommitted 讀未提交,一個事務讀到另一個事務沒有提交的數據。
a) 存在:3個問題(臟讀、不可重復讀、虛讀)。
b) 解決:0個問題
- read committed 讀已提交,一個事務讀到另一個事務已經提交的數據。
a) 存在:2個問題(不可重復讀、虛讀)。
b) 解決:1個問題(臟讀)
- repeatable read :可重復讀,在一個事務中讀到的數據始終保持一致,無論另一個事務是否提交。
a) 存在:1個問題(虛讀)。
b) 解決:2個問題(臟讀、不可重復讀)
- serializable 串行化,同時只能執行一個事務,相當於事務中的單線程。
a) 存在:0個問題。
b) 解決:3個問題(臟讀、不可重復讀、虛讀)
l 安全和性能對比
n 安全性:serializable > repeatable read > read committed > read uncommitted
n 性能 : serializable < repeatable read < read committed < read uncommitted
l 常見數據庫的默認隔離級別:
n MySql:repeatable read
n Oracle:read committed
網絡協議 finally{ return問題 註入問題 jdbc註冊驅動問題 PreparedStatement 連接池目的 1.2.1DBCP連接池 C3P0連接池 MYSQL兩種方式進行實物管理 JDBC事務 DBUtils事務 ThreadLocal 事務特性 並發訪問 隔離級別