天天看点

java处理mysql中的事务及SavePoint的用法

事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言

(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。

事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。

例如:在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。

我对事务的理解最深的还是原子性;即,要么全部操作成功,要么都失败。

在数据库操作中,有时候一个功能的实现要涉及到多个表的操作,我们就以此为一个事务,必须保证多个表的变化都执行,

那么该怎么处理呢?

在这里以java、mysql数据库为例,银行转账问题(事务)

事务描述:用户a给用户b汇款x,数据库表中会有两个操作,a用户的账目数减少x,b用户账目数增加x。

只有当b用户收到钱时,两个操作才回执行,否则都不执行,两人账户不变。

模拟操作:

public class BankExample {

	private static String conStr = "jdbc:mysql://localhost/test";
	private String root = "root";
	private String pwd = "123";
	
	static{
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public Connection getCon(){
		try {
			return DriverManager.getConnection(conStr, root, pwd);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static void main(String[] args) {
		BankExample be = new BankExample();
		
		Connection con = null;
		Savepoint sp = null;
		int x = 0;
		try {
			con = be.getCon();
			con.setAutoCommit(false);//设置自动递交关闭
			//操作一 a用户减去x
			String sql = "insert into a_bank values(null,?)";
			PreparedStatement pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, 1000 - x);
			pstmt.executeUpdate();
			
			//操作二 b用户 加上 x
			String sql1 = "insert into b_bank values(null,?)";
			PreparedStatement pstmt1 = con.prepareStatement(sql1);
			pstmt1.setInt(1, 1000 + x);
			pstmt1.executeUpdate();
			
			sp = con.setSavepoint();//设置断点
			
			//打印凭条
			PreparedStatement ps = con.prepareStatement("seltct * from result id=?");
			ps.setString(1, "33");
			ResultSet rs = ps.executeQuery();
			System.out.println(rs.getString("name"));
			
		} catch (SQLException e) {
			try {
				con.rollback(sp);//滚回断点
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
		try {
			con.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
           

保证一个事务的原子性的方法就是统一提交setAutoCommit(false),此方法只有当调用commit()方法之后才会提交,

从而保证事务的原子性。

我在上面加了一个打印凭条的例子,以便了解SavePoint,不管有没有凭条转账都可以完成,所以转账和打印凭条是两个事务,

我在打印凭条的操作之前设置一个保存点SavePoint,如果没有凭条了会抛出SQLException异常,我在此处理保存点让进度”滚回到“

设置的地方然后执行就可以了!