使用数据库连接对象管理工具类完成转账案例(最终版)

场景:tom欠jerry1000元,通过银行转账,此过程需要两条sql语句实现

1.update account set money = money - 1000 where name = 'tom';

2.update account set money = money + 1000 where name = 'jerry';

假设两人初始账户都是10000元,那么执行转账操作后,tom账户为9000元,jerry账户为11000元。

通过事务管理来保证两条sql语句同时成功与失败,通过三层设计思想来实现具体操作,通过数据库连接对象管理工具类来保证三层所需要的Connection连接对象都是同一个。

数据库连接对象管理工具类:(使用ThreadLocal类来获取连接对象,保证了连接对象都是同一个。)

/*
    数据库连接对象管理工具类
 */
public class ConnectionManger {
    private static ThreadLocal<Connection> tl = new ThreadLocal<>();

    private ConnectionManger(){}
    /*
        定义静态方法,获取连接对象
        此方法,保证获取到的是同一个Connection连接对象
     */
    public static Connection getConnection() throws SQLException {
        //首先从ThreadLocal对象中获取Connection对象
        Connection con = tl.get();
        //判断con是否为null
        if (con == null){
            //获取一个连接对象
            con = C3P0Util.getConnection();
            //绑定到ThreadLoacl中
            tl.set(con);
        }
        return con;
    }
    /*
        定义开启事务的方法
     */
    public static void setAutoCommit() throws SQLException {
        //通过getConnection方法来保证拿到的都是同一个连接对象
        Connection con = getConnection();
        con.setAutoCommit(false);
    }
    /*
        定义提交事务的方法
     */
    public static void commit() throws SQLException {
        Connection con = getConnection();
        con.commit();
    }
    /*
        定义回滚事务的方法
     */
    public static void rollBack() throws SQLException {
        Connection con = getConnection();
        con.rollback();
        //从ThreadLoacl对象中移除
        tl.remove();
    }
}

dao(数据持久化)层实现:

public class AccountDao {
    //进账方法
    public void in(String inName, double inMoney) throws SQLException {
        //1.创建QueryRunner对象
        QueryRunner qr = new QueryRunner();

        //2.定义sql语句
        String sql = "update account set money = money + ? where name = ?";

        //3.执行sql语句
        qr.update(ConnectionManger.getConnection(),sql,inMoney,inName);
    }
    //出账方法
    public void out(String outName,double outMoney) throws SQLException {
        //1.创建QueryRunner对象
        QueryRunner qr = new QueryRunner();
        //2.定义sql语句
        String sql = "update account set money = money - ? where name = ?";
        //3.执行sql语句
        qr.update(ConnectionManger.getConnection(),sql,outMoney,outName);
    }
}
View Code

service(业务操作)层实现:

public class AccountService {
    //定义转账方法
    public void transfer(String inName, String outName, double transferMoney) {
        Connection con = null;
        try {
            //1.创建dao层对象,用来调用方法
            AccountDao dao = new AccountDao();
            //2.创建连接对象
            con = ConnectionManger.getConnection();
            //3.开启事务
            ConnectionManger.setAutoCommit();
            //4.调用方法
            //进账方法
            dao.in(inName, transferMoney);
//            System.out.println(1/0);
            //出账方法
            dao.out(outName, transferMoney);
            //5.如果执行没有问题,提交事务
            ConnectionManger.commit();
        } catch (Exception e) {
            e.printStackTrace();
            //6.如果执行出现问题,回滚事务
            try {
                ConnectionManger.rollBack();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        } finally {
            //7.释放资源
            C3P0Util.release(con, null, null);
        }
    }
}
View Code

view(页面展示)层实现:

public class AccountPage {
    public static void main(String[] args) {
        //定义进账用户,出账账户
        String outName = "tom";
        String inName = "jerry";
        //创建Service层对象
        AccountService service = new AccountService();
        //调用转账方法
        service.transfer(inName,outName,1000);
    }
}
View Code

成功运行结果:

出现异常时运行结果:(由于事务管理,出现异常时会执行事务回滚,保证转账时的进出的相等)

posted @ 2020-08-28 22:27  硬盘红了  阅读(191)  评论(0编辑  收藏  举报