事務應用-Dao的綜合應用
一、事務應用
1、事務定義
用於完成一件事件的獨立單元 例如:我們在資料庫操作的時候,對資料庫的一次更新可以認為是一個事務,業務中銀行轉賬也可以是一個事務(餘額的變更)
2、事務的四個特性
a、原子性: 一個事務在執行過程中, 要麼全部執行,要麼全部不執行,不可能停滯了中途,及時中途失敗了,也會回滾到初始狀態, 事務是一個不可分割的獨立單元
b、一致性: 事務體現在資料庫操作中,在事務開始前和結束後,它們的完整性約束沒有被破壞,保持前後一致
c、隔離性: 同一時間 ,只允許一個事務處理同一條資料 , 事務和事務相互獨立並隔離, 多個事務之間處理同一條資料 必須考慮事務的隔離級別問題
d、永續性: 事務可以提交(commit),也可以回滾(rollbck) ,事務一旦提交將永久生效,事務的回滾可以返回到修改之前的狀態。
3、MySql中事務演示
預設情況下,MySql的事務是自動提交 ,
查詢事務的提交方式
show variables like 'autocommit';
ON:自動 OFF:關閉
更改事務的提交方式
set @@autocommit =0 ;
注意 以上只能更改當前視窗的事務提交方式,如果需要全域性更改 ,需要在my.ini下 新增如下
set @@autocommit =0 ; 然後重啟mysql服務
-- 手動提交事務
select * from t_user;
update t_user set money =400 where userid =1;
-- 對於沒有提交的記錄 ,會鎖行(行級鎖)
commit;
rollback;
事務的併發產生的問題
1、 髒讀: 事務A 讀取了 事務B未提交的資料 ,假如事務B 對資料更新後,事務A讀取了一次,事務B對資料回滾了, 事務A再次讀取一次,事務A發現 第一次讀的資料是髒資料。
2、不可重複讀: 事務A多次讀取同一條記錄,事務B在期間進行提交了,到時事務A讀取的資料前後不一致,這是屬於 不可重複讀 。
3、幻讀: 對於新增記錄而言, 事務A第一次讀取 與第二個讀取的表資料總行數 不一致 ,不一致原因是 在期間事務B可能添加了記錄 ,導致事務A出現 幻覺多了一條記錄。
MySql的預設隔離級別: 可重複讀取
select @@transaction_isolation
REPEATABLE-READ
修改MySql的隔離級別:
set session transaction isolation level read committed ;
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交資料(read uncommitted) | 是 | 是 | 是 |
讀已提交資料(read committed) | 否 | 是 | 是 |
可重複讀(repeatable-read ) | 否 | 否 | 是 |
序列化(serializable) | 否 | 否 | 否 |
4、JDBC中 事務的手動提交
預設情況下 JDBC的事務是自動提交的, 由於在特定的業務場景下 一個事務需要執行多個sql語句 ,例如轉賬業務 ,賬戶A給賬戶B轉賬100元, 賬戶A的餘額需要減少100 , 而賬戶B的餘額要增加100 (2個sql)
public static void main(String[] args) {
// 賬戶A 給賬戶B 轉賬
MyUser fromUser = new MyUser();
fromUser.setUserid(1);
MyUser toUser = new MyUser();
toUser.setUserid(2);
Scanner sc = new Scanner(System.in);
System.out.println("請輸入轉賬的金額");
double money = sc.nextDouble();
// 獲取連線物件
Connection conn = null;
PreparedStatement ps = null;
// 設定該連線為 手動提交事務
try {
conn = DBUtil.getConn();
conn.setAutoCommit(false);
String sql1 = "update t_user set money = money-"+money +" where userid = ?";
ps = conn.prepareStatement(sql1);
// 設定引數
ps.setInt(1,fromUser.getUserid());
// 執行
int count1= ps.executeUpdate();
System.out.println("count1----"+count1);
//模擬突然斷電
System.out.println(10/0);
// 另一個賬戶的錢 增多
sql1 = "update t_user set money = ifnull(money,0)+"+money +" where userid = ?";
ps = conn.prepareStatement(sql1);
ps.setInt(1,toUser.getUserid());
//執行
int count2 = ps.executeUpdate();
System.out.println("count2----"+count2);
// 提交事務
conn.commit();;
System.out.println("轉賬成功");
} catch (Exception e) {
e.printStackTrace();
// 回滾
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println("轉賬失敗");
} finally {
//關閉連線
DBUtil.closeAll(conn , ps , null);
}
}
二、DAO的綜合應用
建立圖書表和 使用者表 ,完成後臺圖書管理系統。
1、建立獨立專案: 專案包括 dao 、entity、 util包
dao中不同的表提供不同的介面 和 實現類
entity中提供對應表的實體類
util包裝 提供 DBUtil類
寫一個控制檯程式,呼叫 dao的實現類 (BookDaoImpl、UserDaoImpl)
完成功能:
1、使用者登入,使用者註冊(註冊時驗證使用者是否存在)
2、圖書管理: 新增圖書,刪除圖書,修改圖書,查詢所有圖書,根據ID查詢圖書。
b_user : 使用者id 使用者名稱 密碼 狀態
book :圖書id ,圖書名,圖書作者,圖書價格,圖書釋出時間 ,圖書所屬的userid (外來鍵)
專案分層:
專案名
-|src
-| com.j2008
-|util : DBUtil.java
-| entity: XXX.java ...
-|dao: XXXDao.java
XXXDaoImpl.java
-| client : 測試類 控制檯輸入