1. 程式人生 > 實用技巧 >事務應用-Dao的綜合應用

事務應用-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 : 測試類 控制檯輸入