使用数据库连接对象管理工具类完成转账案例(最终版)
场景: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(数据持久化)层实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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); } }
service(业务操作)层实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(页面展示)层实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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); } }
成功运行结果:
出现异常时运行结果:(由于事务管理,出现异常时会执行事务回滚,保证转账时的进出的相等)
学习的博客多用于在笔记中,防止笔记过于臃肿,所以将样例及运行结果放在博客中,后以超链接的形式记录在笔记中,所以有些博文过于单薄。如果有小伙伴遇到问题欢迎评论,看到就会回复,学渣一枚,加油努力。