事务
来源:互联网 发布:今日头条乱下软件 编辑:程序博客网 时间:2024/06/08 06:28
概述
事务的概念
事务是访问并可能更新数据库中各种数据项的一个程序执行单元。
事务的特点
原子性:一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性:事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性:持久性也称永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
分类
手动事务
在操作数据库的时候,执行了一条增删改的语句,但是磁盘里的数据没有改变,需要手动提交事务之后,磁盘里的数据才发生改变。典型的数据库就是oracle(默认的情况下,可以更改事务类型)。
自动事务
一天增删改语句执行后,磁盘里的数据改变。典型的数据库就是MySql(默认的情况下,可以更改事务类型)。
手动事务
手动事务操作分三个部分,如下:
开启事务:开启一个事务
提交事务:从开启到提交之间的有效SQL语句,将会执行,磁盘数据将会改写,事务结束
事务回滚:从事务到回滚之间的有效SQL语句,将不生效,事务没有结束
案例分析
以MySql数据库为例,实现一个银行转账的小案例。假设有一张数据库表,表有三个字段。
该表中有两个用户
假设张三要给李四转账,要想实现两者的转账,需要两条SQL语句。如果完美的情况下,在程序执行了全部的语句,没问题。但是,如果在只执行第一个语句后,服务器停电了,这样就出现了诡异的现象,张三的钱转出去了,而李四没有收到。这是银行系统不允许的。
结合上文的铺垫,转账就可以看成一个事务,这个事务由两个操作组成。转账要么两条SQL语句全部操作成功,要么全部失败。这种结果才是我们想的。
MySql模拟
理想状态
两条语句都执行:
结果:非理想状态
只执行一条语句:
结果:
可以看到自动事务,在非理想状态下,相当的不靠谱,为了避免出现这种情况,MySql提供的手动事务的语句
start transaction开启事务
rollback回滚事务
commit提交事务
理想状态
在执行更改操作前先执行start transaction
结果:
执行commit
结果:非理想状态(懒得更改表单数据了,在上次更改的基础上进行)
在执行更改操作前先执行start transaction
执行rollback
执行commit
结果:
通过以上四个模拟,手动事务的优越性就体现出来了。
案例实现
- 表单界面
<!DOCTYPE html><html><head><meta charset="UTF-8"><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-8"); //获取到请求的数据 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(); } }}
头一次写这么长的博文,算是简单系统的梳理了一下事务。主要为了加深记忆,另一方面希望能帮助一些初学者。
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- 事务
- Hololens官方教程精简版 - 05. Voice(语音)
- PAT BASIC LEVEL 1010. 一元多项式求导 (25)
- 数据库中的 date datetime timestamp的区别
- 一致性Hash(Consistent Hashing)原理剖析
- java集合之Set与List总结
- 事务
- Netty4.x中文教程系列(四)编解码器Codec
- 寒假05:最大最小公倍数、K好数
- 《盲女惊魂记》
- python标准模块——time
- 兔子-android studio中安装butterknife插件
- C#使用Monitor类、Lock和Mutex类进行多线程同步
- 小记-STM8S003F3端口复用和端口开漏
- 自定义ViewGroup神器ViewDragHelper