好记性不如烂笔头25-JAVA处理数据库事务(3) - 事务回滚点


在具体的工作中,有的事情需要被保持,不需要回滚,有的工作需要回滚,而这些逻辑,可以通过手动设置事务的回滚点。

1、用JAVA处理数据库事务的事务回滚点的准备

要有一个能够访问数据库的应用。下面的示例都基于ORACLE进行。

create table ffm_account(

   id int primary key ,

   name varchar(32),

   money int

);

测试数据:

insert into ffm_account(id,name,money)values(1,‘A‘,1000);

insert into ffm_account(id,name,money)values(2,‘B‘,1000);

 

2、JDBC中使用回滚点进行事务处理

在JDBC中使用如下的语句设置事务回滚点:

 Savepoint sp = conn.setSavepoint();

 Conn.rollback(sp);

 Conn.commit();//回滚后提交事务

 

3、JDBC使用事务范例之脏数据 以及读取脏数据的源代码

在JDBC代码中演示银行转帐案例,有两个银行账户,A和B,各自有1000块钱;A在银行购买了一个VIP服务,花费10元钱;然后 A往B账户转账100块。

在本样例中,购买VIP服务不需要回滚,A往B账户转账,如果转账失败,需要回滚。

JAVA源代码:

package com.transaction;

 

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Savepoint;

 

import com.db.EasyC3p0;

 

/**

 *有两个银行账户,A和B,各自有1000块钱;A在银行购买了一个VIP服务,花费10元钱;然后 A往B账户转账100块。

 *在本样例中,购买VIP服务不需要回滚,A往B账户转账,如果转账失败,需要回滚。

 *

 *@author 范芳铭

 */

public class EasySavepoint {

    publicstatic void main(String[] args)   throwsSQLException{

        EasySavepointpoint = new EasySavepoint();

        //首先对账户进行操作

        point.OperAccount();

        //查看账户执行情况

        point.afterRunResult();

 

    }

   

    publicvoid OperAccount() throws SQLException{

        Connectionconn = null;

        PreparedStatementstmt = null;

        ResultSetrs = null;

        Savepointsp = null;

        try{

            conn= EasyC3p0.getConnection();

            //通知数据库开启事务(start transaction)

            //=================================

            conn.setAutoCommit(false);

            StringsqlAllMoney = " select sum(money) as money from ffm_account ";

            StringsqlA_money = " select money from ffm_account ";

            stmt= conn.prepareStatement(sqlAllMoney);

            rs = stmt.executeQuery();

            if(rs.next()) {

                System.out.println("转账执行前,系统中全部金额为:" +rs.getInt("money"));

            }

            stmt= conn.prepareStatement(sqlA_money);

            rs= stmt.executeQuery();

            if(rs.next()) {

                System.out.println("转账执行前,A的金额为:"+ rs.getInt("money"));

            }

            //=================================

            //A账户购买VIP服务,花费10元

            StringsqlA = "update ffm_account set money=money-100 where name=‘A‘";

            stmt= conn.prepareStatement(sqlA);

            stmt.executeUpdate();

           

            //设置事务回滚点

            sp= conn.setSavepoint();

           

            //简单模拟A往B账户转账:

            sqlA= "update ffm_account set money=money-100 where name=‘A‘";

            stmt= conn.prepareStatement(sqlA);

            stmt.executeUpdate();

            //系统中有B账户,但是发生了异常

            //简单粗暴的让任务出现异常中断

            intx = 1/0;

            Stringsqlc = "update ffm_account set money=money+100 where name=‘C‘";

            stmt= conn.prepareStatement(sqlc);

            stmt.executeUpdate();

            conn.commit();

            //简单模拟A往B账户 结束

            //=================================

 

 

        }catch (Exception e) {

            //回滚到设置的事务回滚点

            conn.rollback(sp);

            //回滚后要提交事务

            conn.commit();

            e.printStackTrace();

        }finally {

            EasyC3p0.close(conn,stmt, rs);

        }  

    }

   

    publicvoid afterRunResult(){

        Connectionconn = null;

        PreparedStatementstmt = null;

        ResultSetrs = null;

        try{

            conn = EasyC3p0.getConnection();

            //通知数据库开启事务(starttransaction)

            //=================================

            conn.setAutoCommit(false);

            StringsqlAllMoney = " select sum(money) as money from ffm_account ";

            StringsqlA_money = " select money from ffm_account ";

           

            //转账结束后,看账户情况

            stmt= conn.prepareStatement(sqlAllMoney);

            rs= stmt.executeQuery();

            if(rs.next()) {

                System.out.println("转账执行后,系统中全部金额为:" +rs.getInt("money"));

            }

            stmt= conn.prepareStatement(sqlA_money);

            rs= stmt.executeQuery();

            if(rs.next()) {

                System.out.println("转账执行后,A的金额为:"+ rs.getInt("money"));

            }

 

        }catch (Exception e) {

            e.printStackTrace();

        }finally {

            EasyC3p0.close(conn,stmt, rs);

        }  

    }

}

 

4、运行结果

转账执行前,系统中全部金额为:2000

转账执行前,A的金额为:1000

java.lang.ArithmeticException: / by zero

    atcom.transaction.EasySavepoint.OperAccount(EasySavepoint.java:64)

    atcom.transaction.EasySavepoint.main(EasySavepoint.java:21)

转账执行后,系统中全部金额为:1900

转账执行后,A的金额为:900

 

系统虽然在运行中出现了异常,但是达到了预期的效果。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。