事务:保证操作的一致性,要么操作同时成功,要么同时失败;

最经典的例子就是转账:A向B转账,如果转账成功,那么必然A的钱减少,B的钱增多;如果转账失败,那么必然是A和B的余额都没有发生变化;这个例子就用到了事务操作;

Mysql 对事物的支持:

序号          命令                                  描述

1               set autocommit = 0          关闭自动提交

2               set autocommit = 1          打开自动提交

3               begin                               启动事务

4               commit                             提交事务        

5               rollback                            回滚

如图1,先建立一个user表

mysql使用事务查询 mysql如何使用事务_mysql使用事务查询

我们来插入一个数据:

利用:insert into  user(id,password,money) values(1004,'abcdef',999999999);

mysql使用事务查询 mysql如何使用事务_bc_02

查一下表发现添加成功,可是毕竟我们普通人没有10亿差一块这么多的钱,这个数字输入错误,想回到之前正确的状态怎么办呢,不用想了,肯定回不去了,因为这个值已经写入硬盘了。为了避免这种情况发生,就需要用到事务了。

首先,设置取消自动提交

set autocommit = 0;

然后开启事务

begin;

然后插入一条语句

insert into  user(id,password,money) values(1005,'abcdef',999999999);

mysql使用事务查询 mysql如何使用事务_java_03

哎妈呀,发现插错了怎么办呢,别急咱们这次可以回滚

rollback;

mysql使用事务查询 mysql如何使用事务_sql_04

这下可以看到,已经滚回去了;

如果提交的是正确的数据怎么办,这时就要用commit来提交事务

commit;

mysql使用事务查询 mysql如何使用事务_mysql使用事务查询_05

现在就已经提交成功了,我们在回滚试试:

rollback;

mysql使用事务查询 mysql如何使用事务_mysql使用事务查询_06

回滚之后,数据依然存在。


然后再JDBC中使用事务

新建一个Basedao 类,里面有打开关闭数据库连接的方法


package com.yanglf;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
public class Basedao {
	
	final static String driver = "com.mysql.jdbc.Driver";
	final static String dburl = "jdbc:mysql://localhost:3306/db";
	final static String name = "root";
	final static String password = "745412";
	
	Connection con = null;
	PreparedStatement ps = null;
	ResultSet rs = null;
	
	public  void openCon() throws  Exception {
		
		Class.forName(driver);
		con = DriverManager.getConnection(dburl,name,password);
		System.out.println(con);
		
	}
	public void closeCon() throws Exception{
		if(ps!=null){
			ps.close();
		}
		if(rs!=null){
			rs.close();
		}
		if(con!=null){
			con.close();
		
		}
	}

}

然后建立main 方法开始测试


package com.yanglf;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;

import com.mysql.jdbc.PreparedStatement;

public class GetMessage {

	/**
	 * @param args
	 * @throws SQLException 
	 * @throws Exception 
	 */
	public static void main(String[] args)  {
		Basedao tj = new Basedao();
	
		try {
			
			tj.openCon();
			
			//注意与在数据库中操作有点不同,数据库为set autocommit = 0;
			tj.con.setAutoCommit(false);
			//利用占位符,减少字符串拼接的麻烦
			String sql1 = "insert into record (id,date,money,state) values (?,?,?,?);";
		
			//插入一条存入200块钱的数据
			tj.ps = tj.con.prepareStatement(sql1);
			tj.ps.setInt(1, 1003);
			tj.ps.setLong(2, new Date().getTime());
			tj.ps.setInt(3, 100);
			tj.ps.setString(4, "存入");
		
			//修改添加删除信息返回的是受影响行数
			int row = tj.ps.executeUpdate();
			//在同时插入一条取出300的数据记录
			tj.ps = tj.con.prepareStatement(sql1);
			tj.ps.setInt(1, 1003);
			tj.ps.setLong(2, new Date().getTime());
			tj.ps.setInt(3, 300);
			tj.ps.setString(4, "取出");
			int row2 = tj.ps.executeUpdate();
			
			//提交事务
			tj.con.commit();
		} catch (Exception e) {
			try {
				//回滚
				tj.con.rollback();
			} catch (SQLException e1) {
				
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		
		
		//然后来查询下表
		String sql2 = "select * from record;";
		
		
		
		try {
			tj.ps = tj.con.prepareStatement(sql2);
			tj.rs = tj.ps.executeQuery();//查询结果返回的是表
		} catch (SQLException e1) {
	
			e1.printStackTrace();
		}
		
		
		try {
			while (tj.rs.next()) {
			//控制台输出下查询到的信息
			System.out.println(tj.rs.getInt("id")+"\t"+new Timestamp(tj.rs.getLong("date"))+"\t"+
			tj.rs.getInt("money")+"\t"+tj.rs.getString("state"));
				
			}
		} catch (SQLException e) {
			
			e.printStackTrace();
		}
		
		
		try {
			tj.closeCon();//关闭数据连接
		} catch (Exception e) {
			
			e.printStackTrace();
		}

	}

}



两次添加如果设置正确则控制台显示:(上面两条数据是数据库本身有的,最后两条是新添加的)

com.mysql.jdbc.JDBC4Connection@7bc9a690
1001 2016-05-16 23:28:06.492 322 转出
1002 2016-05-16 23:28:06.499 322 转入
1003 2016-05-21 00:37:06.895 100 存入
1003 2016-05-21 00:37:06.898 300 取出

同时也可以修改添加数据,比如将下面的这一句注释掉,由于数据库设置存入,取出状态非空,所以这次插入会报异常


tj.ps.setString(4, "取出");

查询的结果只能查到前面两句,因为出现异常,在catch块中进行了回滚,使得第一条插入的数据又得到恢复;这正是事务的作用。

一句话:事务是为了保证数据的一致性和完整性