多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 數據庫 > 數據庫應用 > 事務

事務

來源:程序員人生   發布時間:2017-02-06 08:03:34 閱讀次數:3467次

概述

事務的概念

事務是訪問并可能更新數據庫中各種數據項的1個程序履行單元。

事務的特點

原子性:1個事務是1個不可分割的工作單位,事務中包括的諸操作要末都做,要末都不做。
1致性:事務必須是使數據庫從1個1致性狀態變到另外一個1致性狀態。1致性與原子性是密切相干的。
隔離性:1個事務的履行不能被其他事務干擾。即1個事務內部的操作及使用的數據對并發的其他事務是隔離的,并發履行的各個事務之間不能相互干擾。
持久性:持久性也稱永久性,指1個事務1旦提交,它對數據庫中數據的改變就應當是永久性的。接下來的其他操作或故障不應當對其有任何影響。

分類

手動事務

在操作數據庫的時候,履行了1條增刪改的語句,但是磁盤里的數據沒有改變,需要手動提交事務以后,磁盤里的數據才產生改變。典型的數據庫就是oracle(默許的情況下,可以更改事務類型)。

自動事務

1天增刪改語句履行后,磁盤里的數據改變。典型的數據庫就是MySql(默許的情況下,可以更改事務類型)。

手動事務

手動事務操作分3個部份,以下:
開啟事務:開啟1個事務
提交事務:從開啟到提交之間的有效SQL語句,將會履行,磁盤數據將會改寫,事務結束
事務回滾:從事務到回滾之間的有效SQL語句,將不生效,事務沒有結束


案例分析

MySql數據庫為例,實現1個銀行轉賬的小案例。假定有1張數據庫表,表有3個字段。
這里寫圖片描述

該表中有兩個用戶

這里寫圖片描述

假定張3要給李4轉賬,要想實現二者的轉賬,需要兩條SQL語句。如果完善的情況下,在程序履行了全部的語句,沒問題。但是,如果在只履行第1個語句后,服務器停電了,這樣就出現了詭異的現象,張3的錢轉出去了,而李4沒有收到。這是銀行系統不允許的。

結合上文的鋪墊,轉賬就能夠看成1個事務,這個事務由兩個操作組成。轉賬要末兩條SQL語句全部操作成功,要末全部失敗。這類結果才是我們想的。

MySql摹擬

  • 理想狀態
    兩條語句都履行:
    這里寫圖片描述
    結果:
    這里寫圖片描述

  • 非理想狀態
    只履行1條語句:
    這里寫圖片描述
    結果:
    這里寫圖片描述

可以看到自動事務,在非理想狀態下,相當的不靠譜,為了不出現這類情況,MySql提供的手動事務的語句
start transaction開啟事務
rollback回滾事務
commit提交事務

  • 理想狀態
    在履行更改操作前先履行start transaction
    這里寫圖片描述
    結果:
    這里寫圖片描述
    履行commit
    這里寫圖片描述
    結果:
    這里寫圖片描述

  • 非理想狀態(懶得更改表單數據了,在上次更改的基礎上進行)
    在履行更改操作前先履行start transaction
    這里寫圖片描述
    履行rollback
    這里寫圖片描述
    履行commit
    這里寫圖片描述
    結果:
    這里寫圖片描述

通過以上4個摹擬,手動事務的優越性就體現出來了。

案例實現

  • 表單界面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF⑻">
<title>Insert title here</title>
</head>
<body>
    <h1>轉賬窗口</h1>
    <form action="/day19/TransAccServlet" method="post">
        轉出人:<input type="text" name="outer"><br>
        轉入人:<input type="text" name="inner"><br>
        總金額:<input type="number" name="money"><br>
        <input type="submit" value="肯定">
    </form>

</body>
</html>
  • XML配置
  <servlet>
    <description></description>
    <display-name>TransAccServlet</display-name>
    <servlet-name>TransAccServlet</servlet-name>
    <servlet-class>com.itheima.servlet.TransAccServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>TransAccServlet</servlet-name>
    <url-pattern>/TransAccServlet</url-pattern>
  </servlet-mapping>
  • 工具類
package com.itheima.utils;

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

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DBUtils {
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
    private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();

    /**
     * 取得數據源
     */
    public static DataSource getDataSource() {
        return dataSource;
    }

    /**
     * 取得數據庫連接
     * @throws SQLException 
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    /**
     * 取得當前線程綁定的連接
     * @throws SQLException 
     */
    public static Connection getCurrentConnection() throws SQLException {
        Connection conn = tl.get();
        if (conn==null) {
            conn = getConnection();
            tl.set(conn);
        }

        return conn;
    }

    /**
     * 開啟事務
     * @throws SQLException 
     */
    public static void beginTransaction() throws SQLException {
        Connection conn = getCurrentConnection();
        conn.setAutoCommit(false);
    }

    /**
     * 回滾事務
     * @throws SQLException 
     */
    public static void rollbackTransaction() throws SQLException {
        Connection conn = getCurrentConnection();
        conn.rollback();
    }

    /**
     * 提交事務
     * @throws SQLException 
     */
    public static void commitTransaction() throws SQLException {
        Connection conn = getCurrentConnection();
        conn.commit();
        conn.close();
        tl.remove();
    }
}
  • servlet類
package com.itheima.servlet;

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.itheima.service.TransferService;

public class TransAccServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf⑻");

        //獲得到要求的數據
        String outer = request.getParameter("outer");
        String inner = request.getParameter("inner");
        String money = request.getParameter("money");

        //將數據傳遞給業務邏輯
        TransferService service = new TransferService();
        boolean result = service.transferAcc(outer, inner, money); 

        //根據業務邏輯的反饋信息,處理后響應給閱讀器
        if (result) {
            //轉賬成功
            response.getWriter().write("轉賬成功");
        } else {
            //轉賬失敗
            response.getWriter().write("轉賬失敗");
        }
    }

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

}
  • service類
package com.itheima.service;

import java.sql.SQLException;

import com.itheima.dao.TransferDao;
import com.itheima.utils.DBUtils;

public class TransferService {

    public boolean transferAcc(String outer, String inner, String money) {
        boolean flag = true;
        TransferDao dao = new TransferDao();

        try {
            // 開啟事務
            DBUtils.beginTransaction();

            dao.out(outer, money);
            dao.in(inner, money);
        } catch (Exception e) {
            try {
                flag = false;
                //回滾事務
                DBUtils.rollbackTransaction();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            try {
                //提交事務
                DBUtils.commitTransaction();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return flag;
    }

}
package com.itheima.dao;

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

import org.apache.commons.dbutils.QueryRunner;

import com.itheima.utils.DBUtils;

public class TransferDao {

    public void out(String outer, String money) throws SQLException {
        QueryRunner qr = new QueryRunner();
        Connection conn = DBUtils.getCurrentConnection();
        String sql = "update account set money=money-? where username=?";
        int line = qr.update(conn, sql, money, outer);

        if (line<1) {
            throw new SQLException();
        }
    }

    public void in(String inner, String money) throws SQLException {
        QueryRunner qr = new QueryRunner();
        Connection conn = DBUtils.getCurrentConnection();
        String sql = "update account set money=money+? where username=?";
        int line = qr.update(conn, sql, money, inner);

        if (line<1) {
            throw new SQLException();
        }
    }

}

頭1次寫這么長的博文,算是簡單系統的梳理了1下事務。主要為了加深記憶,另外一方面希望能幫助1些初學者。

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 欧美日韩国产精品va | 国产91在线九色 | 精品欧美一区二区三区在线观看 | 亚洲成人国产精品 | 中文字幕乱码在线 | 日韩亚色| 久久一区二区三区99 | 高清国产一区二区 | 亚洲午夜久久影院 | 在线视频日韩欧美 | 激情一区二区三区 | 国产人做人爱视频精品 | 久久久国产高清 | 性欧美乱又伦 | 美女上床视频 | 性配久久久 | 亚洲 欧美综合小说区图片区 | 日产免费线路一区二区三区 | 亚洲免费人成在线视频观看 | free性欧美xxx| 亚洲精品无码专区在线播放 | 亚洲和欧美毛片久久久久 | 国产欧美日韩在线人成aaaa | 欧美18一14sex性处hd | 精品国产亚洲一区二区在线3d | 中文字幕在线观看一区 | h免费在线观看 | 国产精品欧美亚洲韩国日本不卡 | 中文字幕亚洲精品 | 亚洲欧美日韩中文字幕网址 | 日本aaaa片毛片免费观看 | 久久免费国产精品一区二区 | 亚洲第一黄色网 | 久久99精品久久久久久国产越南 | 日本高清中文字幕一区二区三区 | 亚洲日韩欧美综合 | 亚洲精品成人一区二区aⅴ 亚洲精品成人在线 | 欧美free嫩交video | 国产精品久久久亚洲456 | 无遮挡免费视频 | 一级做a爰片性色毛片男 |