上一篇博客讲了CallableStatement接口调用存储过程,这一篇博客我来说说JDBC的事务处理,这在以后的项目开发中也很重要,只有充分地考虑好JDBC的事务处理,才能在项目开发中遇到前台与后台异常时,JDBC的事务处理可以很好地去弥补这一措施,在银行,支付宝,金融,微信红包等等中尤其显得重要,不然的话如果我们给别人转钱时发生异常,钱从我们的卡里扣出来了,但是对方却没有收到,岂不是尴尬了,怎么样?这个例子,一提到钱,眼睛就雪亮雪亮的,是不是对JDBC事务处理产生了好奇心,现在我就来说说JDBC的事务处理。
事务处理:英文名字:Transaction Processing;用于正确有效的记录自己感性的数据处理记录。事务(由几个任务组成)是一个最小的工作单元,无论成功与否都要作为一个整体进行即要么全部执行要么全部都不执行,不存在执行了一部分另一部分没有执行的情况发生。从而得出事务本身具有ACID的属性。ACID就是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
原子性( Atomicity):是事务的最小单元,是不可在分割的单元,相当于一个个小的数据库操作,这些操作必须同时成功才为成功,只要有一个失败,则一切的操作都将失败,这就是原子性。
一致性(Consistency):事务在系统完整性中实施一致性,通过保证系统的任何事务最后都处于有效状态来实现。如果事务操作成功,那么系统的所有变化将正确的应用于系统中,系统处于有效状态。如果事务操作中出现错误,那么系统中的所有事务将自动的发生回滚,返回到操作前的状态来保持系统的一致性。
隔离性(Isolation):在隔离的状态执行事务,使它们觉得好像是系统在某一个给定的时间段内执行唯一的操作,如果有两个事务,运行在相同的时间段内,执行着相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用这个系统。
持久性(Durability):事务完成之后,它对于系统的影响将是永久的。即使该修改会产生致命的错误也会一直保持下去,直到有人修改了为止。
这里我们来说一说mysql数据库中的事物处理:它是由一个或者多个SQL语句序列结合在一起形成所形成的逻辑处理单元。事物处理中的每一条语句都是完成数据库整个操作任务的一部分,所有的SQL语句结合在一起执行完毕,才能达到完成指定的目的。DBMS在对事务处理中的语句进行处理时,是按照一个约定成俗的规定进行处理的:事务处理中的所有语句都将被作为一个原子性的工作单位,所有语句要么成功的一起执行,要么一个也不执行。有了这种规定,在以后事务处理中发生异常就按照这种规定进行下去,保证了数据库中的数据不会有脏数据的发生。不会产生巨大的危害,减轻了DBMS人员操作负担。
mysql对事务处理的支持的命令:
1:begin:启动事务相当于执行Start Transaction.
2:Start Transaction:启动事务.
3:set autocommit=0/1:为0代表取消自动提交处理,开启事务处理;为1代表打开自动提交处理,关闭事务处理,系统默认情况为1.
4:commit:提交事务.
5:rollback:回滚全部事务.
6:savepoint 事务保存点的名称:设置事务保存点.
7:rollback to savepoint 保存点名称:回滚操作到设置的保存点。
讲了这个多理论性的知识,再上一个代码示例来巩固一下知识,(无代码,不程序嘛) 既然老提及钱,那我们这个例子就举个和钱有关的例子吧。A借B10块钱,A还B10块钱。
创建表:
CREATE TABLE t_money(
id INT PRIMARY KEY AUTO_INCREMENT,
userName VARCHAR(20),
money INT
);
JDBC转账(借钱还钱)代码:
package com.panli.dbutil;
/**
* 连接数据库
*/
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DbUtil {
//数据库驱动名字
private static String jdbcName = "com.mysql.jdbc.Driver";
//数据库协议地址
private static String dbUrl = "jdbc:mysql://localhost:3306/db_user";
//数据库用户名
private static String dbUser = "root";
//数据库密码
private static String dbPassword = "123456";
/**
* 获取连接
* @return
* @throws Exception
*/
public static Connection getCon() throws Exception{
Class.forName(jdbcName);
Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
return conn;
}
/**
* 关闭连接
* @param stmt
* @param conn
* @throws Exception
*/
public static void close(Statement stmt,Connection conn) throws Exception{
if(stmt!=null){
stmt.close();
if(conn!=null){
conn.close();
}
}
}
/**
* 关闭连接
* @param cstmt
* @param conn
* @throws Exception
*/
public static void close(CallableStatement cstmt, Connection conn) throws Exception{
if(cstmt!=null){
cstmt.close();
if(conn!=null){
conn.close();
}
}
}
/**
* 关闭连接
* @param pstmt
* @param conn
* @throws SQLException
*/
public static void close(PreparedStatement pstmt, Connection conn) throws SQLException{
if(pstmt!=null){
pstmt.close();
if(conn!=null){
conn.close();
}
}
}
/**
* 重载关闭方法
* @param pstmt
* @param conn
* @throws Exception
*/
public void close(ResultSet rs,PreparedStatement pstmt, Connection conn) throws Exception{
if(rs!=null){
rs.close();
if(pstmt!=null){
pstmt.close();
if(conn!=null){
conn.close();
}
}
}
}
}
package com.panli.model;
public class Money {
private int id;
private String userName;
private int money;
/**
* 默认的构造方法
*/
public Money() {
super();
// TODO Auto-generated constructor stub
}
/**
* 2个参数的构造方法
* @param id
* @param money
*/
public Money(int id, int money) {
super();
this.id = id;
this.money = money;
}
/**
* 3个参数的构造方法
* @param id
* @param userName
* @param money
*/
public Money(int id, String userName, int money) {
super();
this.id = id;
this.userName = userName;
this.money = money;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
package com.panli.dao;
/**
* 借钱与收钱为一个事务处理事件单元的JDBC代码
*/
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;
import com.panli.dbutil.DbUtil;
import com.panli.model.Money;
public class UserMoneyOutInDao {
private static DbUtil dbUtil = new DbUtil();
/**
* 借出钱给他人方
* @param money
* @return
* @throws Exception
*/
private static int OutMoney(Money money)throws Exception{
Connection conn = dbUtil.getCon();
String sql = "update t_money set money=money-? where id = ? ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, money.getMoney());
pstmt.setInt(2, money.getId());
int result = pstmt.executeUpdate();
dbUtil.close(pstmt, conn);
return result;
}
/**
* 借到钱的一方
* @param money
* @return
* @throws Exception
*/
private static int InMoney(Money money)throws Exception{
Connection conn = dbUtil.getCon();
String sql = "update t_money set money=money+? where id = ? ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, money.getMoney());
pstmt.setInt(2, money.getId());
int result = pstmt.executeUpdate();
dbUtil.close(pstmt, conn);
return result;
}
public static void main(String[] args) {
int moneys = 10;
Money Age = new Money(1, moneys);
Money Bge = new Money(2, moneys);
Connection conn1 = null;
Savepoint sp = null;
try {
conn1 = dbUtil.getCon();
//取消自动提交事务
conn1.setAutoCommit(false);
//设置事务保存点,如果发生错误则回滚到此处
sp = conn1.setSavepoint();
//Age借出钱给Bge
OutMoney(Age);
System.out.println("Age借钱成功!");
//Bge收到钱
InMoney(Bge);
System.out.println("Bge收到钱成功!");
} catch (Exception e) {
// TODO Auto-generated catch block
try {
//如果遇到错误就回滚
conn1.rollback(sp);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("Age借钱失败!");
System.out.println("Bge收到钱失败!");
e.printStackTrace();
}finally{
try {
//如果事务操作成功,提交事务
conn1.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
//关闭连接
conn1.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("钱财交易成功!");
}
}