事务

事务

基本概念:

       事务使指一组最小逻辑操作单元,里面有多个操作组成。组成事务的每一部分必须要同时提交成功,如果有一个操作失败,整个操作就回滚。

 

事务ACID特性

原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 

一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。

隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

 

事务的特性:

      原子性,是一个最小逻辑操作单元 !

      持久性, 事务一旦提交成功,对数据的更改会反映到数据库中。

      隔离性, 事务与事务之间是隔离的。


API:

|-- Connection

       void setAutoCommit(boolean autoCommit) ;  设置事务是否自动提交,如果设置为false,表示手动提交事务。

       void commit() ();                                                       手动提交事务

       void rollback() ;                                                          回滚(出现异常时候,所有已经执行成功的代码需要回退到事务开始前的状态。)

       Savepoint setSavepoint()                                        设置回滚点

       void rollback(Savepoint sp)                                     回滚到指定位


Demo如下:

package com.cn.trans;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Savepoint;

import org.junit.Test;

import com.cn.Util.JdbcUtil;

public class AccountDao {
	
	//全局参数
	private Connection conn= null;
	private PreparedStatement pstmt = null;

	//使用事务控制转账业务
	@Test
	public void trans(){
		
		try {
			//获取连接
			conn = JdbcUtil.getConnection(); //默认开启的隐式事务
			//设置事务为手动提交
			conn.setAutoCommit(false);
			
			//转账sql
			String sql1 = "UPDATE account SET money=money-1000 WHERE accountName = '木丁西'";
			String sql2 = "UPDATE account SET money=money+1000 WHERE accountName = '小刘'";

			//预编译sql1
			pstmt  = conn.prepareStatement(sql1);
			//执行sql1
			pstmt.executeUpdate();
			
			//预编译sql2
			pstmt  = conn.prepareStatement(sql2);
			//执行sql2
			pstmt.executeUpdate();
			
		} catch (Exception e) {
			try {
				conn.rollback();// 出现异常回滚事务
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally{
			try {
				conn.commit();//所有的操作执行成功,则提交事务
			} catch (Exception e) {
				e.printStackTrace();
			}
			JdbcUtil.close(conn, pstmt);
		}
		
	}
	
	//使用事务控制转账业务,回滚到指定的代码
	@Test
	public void trans2(){
		Savepoint sp =  null;
		try {
			//获取连接
			conn = JdbcUtil.getConnection(); //默认开启的隐式事务
			//设置事务为手动提交
			conn.setAutoCommit(false);
			/*************第一次转账****************/
			//转账sql
			String sql1 = "UPDATE account SET money=money-1000 WHERE accountName = '木丁西'";
			String sql2 = "UPDATE account SET money=money+1000 WHERE accountName = '小刘'";
			//预编译sql1
			pstmt  = conn.prepareStatement(sql1);
			//执行sql1
			pstmt.executeUpdate();			
			//预编译sql2
			pstmt  = conn.prepareStatement(sql2);
			//执行sql2
			pstmt.executeUpdate();
			
			//回滚到这个位置
			sp = conn.setSavepoint();

			/*************第二次转账****************/
			//转账sql
			String sql3 = "UPDATE account SET money=money-50 WHERE accountName = '木丁西'";
			String sql4 = "UPDATE account SET money=money+50 WHERE accountName = '小刘'";
			pstmt  = conn.prepareStatement(sql3);
			pstmt.executeUpdate();			
			pstmt  = conn.prepareStatement(sql4);
			pstmt.executeUpdate();
			
		} catch (Exception e) {
			try {
				conn.rollback(sp);// 出现异常回滚事务,回滚到指定位置
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally{
			try {
				conn.commit();//所有的操作执行成功,则提交事务
			} catch (Exception e) {
				e.printStackTrace();
			}
			JdbcUtil.close(conn, pstmt);
		}
		
	}
}

JdbcUtil.java

package com.cn.Util;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * jdbc的工具类
 * @author liuzhiyong
 *
 */
public class JdbcUtil {
	private static String url = null;
	private static String user = null;
	private static String password = null;
	private static String driverClass = null;
	
	/**
	 * 静态代码块(只调用一次)
	 */
	static{
		try {
			//读取db.properties文件
			Properties properties = new Properties();
			/**
			 * 
			 * 加载文件
			 * 
			 *  . 代表java的命令运行的目录
			 *  在java项目下,  . java命令的运行目录从项目的根目录MyEclipse工作空间/bin 目录开始
			 *  在web项目下, . java命令的运行目录从tomact/bin 目录开始
			 *  所以不能用.
			 */
			
			/**
			 * 使用类路径的读取方式
			 * 	/  斜杠表示classpath的根目录
			 * 在java项目下,classpath的根目录从bin目录开始
			 * 在web项目下,classpath的根目录从WEB-INF/classes目录开始
			 */
			InputStream in = JdbcUtil.class.getResourceAsStream("/db.properties");
			properties.load(in);
			//读取信息
			url = properties.getProperty("url");
			user = properties.getProperty("user");
			password = properties.getProperty("password");
			driverClass = properties.getProperty("driverClass");
//			System.out.println(url);
//			System.out.println(user);
//			System.out.println(password);
//			System.out.println(driverClass);
			//注册驱动程序
			Class.forName(driverClass);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("驱动程序注册出错!");
		}
	}
	
	/**
	 * 获取连接对象的方法
	 */
	public static Connection getConnection(){
		
		try {
			Connection conn = DriverManager.getConnection(url, user, password);
			return conn;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	/**
	 * 释放资源的重载方法
	 */
	public static void close(Connection conn, Statement stmt, ResultSet rs){
		
		//关闭资源(顺序:后打开,先关闭)
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				System.out.println("ResultSet关闭失败!");
				throw new RuntimeException(e);
			}
		}if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				System.out.println("Statement关闭失败!");
				throw new RuntimeException(e);
			}
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				System.out.println("Connection关闭失败!");
				throw new RuntimeException(e);
			}
		}
	}
	
	/**
	 * 释放资源的重载方法
	 */
	public static void close(Connection conn, Statement stmt){
		
		//关闭资源(顺序:后打开,先关闭)
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				System.out.println("Statement关闭失败!");
				throw new RuntimeException(e);
			}
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				System.out.println("Connection关闭失败!");
				throw new RuntimeException(e);
			}
		}
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值