JavaEE_day19_事務(wù)

一、事務(wù)概述:

1.什么是事務(wù):

一件事情有n個(gè)組成單元 要不這n個(gè)組成單元同時(shí)成功 要不n個(gè)單元就同時(shí)失敗
就是將n個(gè)組成單元放到一個(gè)事務(wù)中

2.mysql的事務(wù):

默認(rèn)的事務(wù):一條sql語(yǔ)句就是一個(gè)事務(wù) 默認(rèn)就開啟事務(wù)并提交事務(wù)。

手動(dòng)事務(wù):

1)顯示的開啟事務(wù)

start transaction

2)事務(wù)提交:代表從開啟事務(wù)到事務(wù)提交 中間的所有的sql都認(rèn)為有效 真正的更新數(shù)據(jù)庫(kù)

commit

3)事務(wù)的回滾: 代表事務(wù)的回滾 從開啟事務(wù)到事務(wù)回滾 中間的所有的 sql操作都認(rèn)為無(wú)效數(shù)據(jù)庫(kù)沒(méi)有被更新

rollback

二、JDBC事務(wù)操作:

默認(rèn)自動(dòng)事務(wù):
執(zhí)行sql語(yǔ)句:executeUpdate() ---- 每執(zhí)行一次executeUpdate方法 代表事務(wù)自動(dòng)提交.

通過(guò)jdbc的API手動(dòng)事務(wù):
開啟事務(wù):conn.setAutoComnmit(false);
提交事務(wù):conn.commit();
回滾事務(wù):conn.rollback();

注意:控制事務(wù)的connnection必須是同一個(gè)空郊;
執(zhí)行sql的connection與開啟事務(wù)的connnection必須是同一個(gè)才能對(duì)事務(wù)進(jìn)行控制静汤。

三逆甜、DBUtils事務(wù)操作:

QueryRunner:

有參構(gòu)造:QueryRunner runner = new QueryRunner(DataSource dataSource);
有參構(gòu)造將數(shù)據(jù)源(連接池)作為參數(shù)傳入QueryRunner教藻,QueryRunner會(huì)從連 接池中獲得一個(gè)數(shù)據(jù)庫(kù)連接資源操作數(shù)據(jù)庫(kù),所以直接使用無(wú)Connection參數(shù) 的update方法即可操作數(shù)據(jù)庫(kù)谜叹。

無(wú)參構(gòu)造:QueryRunner runner = new QueryRunner();
無(wú)參的構(gòu)造沒(méi)有將數(shù)據(jù)源(連接池)作為參數(shù)傳入QueryRunner匾寝,那么我們?cè)谑? 用QueryRunner對(duì)象操作數(shù)據(jù)庫(kù)時(shí)要使用有Connection參數(shù)的方法。

四荷腊、使用ThreadLocal綁定連接資源:

注意:在同一個(gè)項(xiàng)目中旗吁,不管業(yè)務(wù)有多復(fù)雜,只要我們不手動(dòng)創(chuàng)建線程停局,那么各個(gè)方法互相調(diào)用都在同一個(gè)線程中很钓,這為我們線程綁定提供了前提條件。

五董栽、事務(wù)的特性和隔離級(jí)別:

1.事務(wù)的特性ACID:

1)原子性(Atomicity):原子性是指事務(wù)是一個(gè)不可分割的工作單位码倦,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生锭碳。

2)一致性(Consistency):一個(gè)事務(wù)中袁稽,事務(wù)前后數(shù)據(jù)的完整性必須保持一致。

3)隔離性(Isolation):多個(gè)事務(wù)擒抛,事務(wù)的隔離性是指多個(gè)用戶并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí)推汽, 一個(gè)用戶的 事務(wù)不能被其它用戶的事務(wù)所干擾,多個(gè)并發(fā)事務(wù)之間數(shù)據(jù)要相互隔離歧沪。

4)持久性(Durability):持久性是指一個(gè)事務(wù)一旦被提交歹撒,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變 就是永久性的,接下來(lái)即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響诊胞。

2.并發(fā)訪問(wèn)問(wèn)題----由隔離性引起:

如果不考慮隔離性暖夭,事務(wù)存在3中并發(fā)訪問(wèn)問(wèn)題。

1)臟讀:B事務(wù)讀取到了A事務(wù)尚未提交的數(shù)據(jù) ------ 要求B事務(wù)要讀取A事 務(wù)提交的數(shù)據(jù)撵孤;

2)不可重復(fù)讀:一個(gè)事務(wù)中兩次讀取的數(shù)據(jù)的內(nèi)容不一致 ----- 要求的是一個(gè)事 務(wù)中多次讀取時(shí)數(shù)據(jù)是一致的 --- unpdate迈着;

3)幻讀/虛讀:一個(gè)事務(wù)中兩次讀取的數(shù)據(jù)的數(shù)量不一致 ----- 要求在一個(gè)事務(wù)多 次讀取的數(shù)據(jù)的數(shù)量是一致的 --insert delete。

3.事務(wù)的隔離級(jí)別:

1)read uncommitted : 讀取尚未提交的數(shù)據(jù) :哪個(gè)問(wèn)題都不能解決
2)read committed:讀取已經(jīng)提交的數(shù)據(jù) :可以解決臟讀 ---- oracle默認(rèn)的
3)repeatable read:重讀讀刃奥搿:可以解決臟讀 和 不可重復(fù)讀 ---mysql默認(rèn)的
4)serializable:串行化:可以解決 臟讀 不可重復(fù)讀 和 虛讀---相當(dāng)于鎖表
注意:mysql數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別

查看mysql數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別:

select @@tx_isolation

設(shè)置mysql的隔離級(jí)別:

set session transaction isolation level

案例實(shí)現(xiàn):

MyDataSourceUtils.java

package com.zl.utils;

import java.sql.Connection;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class MyDataSourceUtils {

    //獲得Connection裕菠,從連接池中獲取
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
    
    //創(chuàng)建ThreadLocal
     private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); 
    
     //開啟事務(wù)
     public static void startTransaction() throws SQLException{
         Connection conn = getCurrentConnection();
         conn.setAutoCommit(false);
     }
     
     
    //獲得當(dāng)前線程綁定的conn
    public static Connection getCurrentConnection() throws SQLException{
        //從ThreadLocal中尋找當(dāng)前線程是否有對(duì)應(yīng)Connection
        Connection conn = tl.get();
        if(conn==null){
            //獲得一個(gè)新的Connection
            conn=getConnection();
            //將conn資源綁定到ThreadLocal上
            tl.set(conn);
        }
        return conn;
    
    }
    
    public static Connection getConnection() throws SQLException{
        return dataSource.getConnection();
    }

    //回滾事務(wù)
    public static void rollback() throws SQLException {
        getCurrentConnection().rollback();
    }
 
    //提交事務(wù)
    public static void commit() throws SQLException {
        Connection conn = getCurrentConnection();
        conn.commit();
        tl.remove();
        conn.close();
    }
} 

TransferServlet.java

package com.zl.transfer.web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zl.transfer.service.TransferService;

public class TransferServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        //接收轉(zhuǎn)賬的參數(shù)
        String out = request.getParameter("out");
        String in = request.getParameter("in");
        String moneyStr = request.getParameter("money");
        double money = Double.parseDouble(moneyStr);
        
        TransferService service = new TransferService();
        boolean isTransferSuccess = service.transfer(out,in,money);
        
        response.setContentType("text/html;charset=UTF-8");
        if(isTransferSuccess){
            response.getWriter().write("轉(zhuǎn)賬成功");
        }else{
            response.getWriter().write("轉(zhuǎn)賬失敗");
        }
        
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

TransferService.java

package com.zl.transfer.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zl.transfer.service.TransferService;

public class TransferServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        //接收轉(zhuǎn)賬的參數(shù)
        String out = request.getParameter("out");
        String in = request.getParameter("in");
        String moneyStr = request.getParameter("money");
        double money = Double.parseDouble(moneyStr);
        
        TransferService service = new TransferService();
        boolean isTransferSuccess = service.transfer(out,in,money);
        
        response.setContentType("text/html;charset=UTF-8");
        if(isTransferSuccess){
            response.getWriter().write("轉(zhuǎn)賬成功");
        }else{
            response.getWriter().write("轉(zhuǎn)賬失敗");
        }
        
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

TransferDao.java

package com.zl.transfer.dao;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;

import com.zl.utils.DataSourceUtils;
import com.zl.utils.MyDataSourceUtils;

public class TransferDao {

    public void out(String out, double money) throws SQLException {
        QueryRunner runner = new QueryRunner();
        Connection conn = MyDataSourceUtils.getCurrentConnection();
        String sql = "update account set money=money-? where name=?";
        runner.update(conn, sql, money,out);
    }

    public void in(String in, double money) throws SQLException {
        QueryRunner runner = new QueryRunner();
        Connection conn = MyDataSourceUtils.getCurrentConnection();
        String sql = "update account set money=money+? where name=?";
        runner.update(conn, sql, money,in);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市闭专,隨后出現(xiàn)的幾起案子奴潘,更是在濱河造成了極大的恐慌旧烧,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萤彩,死亡現(xiàn)場(chǎng)離奇詭異粪滤,居然都是意外死亡斧拍,警方通過(guò)查閱死者的電腦和手機(jī)雀扶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)肆汹,“玉大人愚墓,你說(shuō)我怎么就攤上這事“好悖” “怎么了浪册?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)岗照。 經(jīng)常有香客問(wèn)我村象,道長(zhǎng),這世上最難降的妖魔是什么攒至? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任厚者,我火速辦了婚禮,結(jié)果婚禮上迫吐,老公的妹妹穿的比我還像新娘库菲。我一直安慰自己,他們只是感情好志膀,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布熙宇。 她就那樣靜靜地躺著,像睡著了一般溉浙。 火紅的嫁衣襯著肌膚如雪烫止。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天戳稽,我揣著相機(jī)與錄音烈拒,去河邊找鬼。 笑死广鳍,一個(gè)胖子當(dāng)著我的面吹牛荆几,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赊时,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼吨铸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了祖秒?” 一聲冷哼從身側(cè)響起诞吱,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤舟奠,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后房维,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沼瘫,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年咙俩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耿戚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阿趁,死狀恐怖膜蛔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情脖阵,我是刑警寧澤皂股,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站命黔,受9級(jí)特大地震影響呜呐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜悍募,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一蘑辑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧搜立,春花似錦以躯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至颠通,卻和暖如春址晕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背顿锰。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工谨垃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人硼控。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓刘陶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親牢撼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匙隔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容