java事务全解析(三)--丑陋的案例
来源:互联网 发布:淘宝手机端买家秀 编辑:程序博客网 时间:2024/04/30 08:33
在本系列的上一篇文章中,我们看到了一个典型的事务处理失败的案例,其主要原因在于,service层和各个DAO所使用的Connection是不一样的,而JDBC中事务处理的作用对象正是Connection对象,所以不同DAO中的操作不在同一个事务里面,从而导致事务失败。从中我们得出了教训:要避免这种失败,我们可以使所有操作共享一个Connection对象,这样应该就没有问题了。
请通过以下方式下载本系列文章的github源代码:
Git clone https://github.com/davenkin/java_transaction_workshop.git
在本篇文章中,我们将看到一个成功的,但是丑陋的事务处理方案,它的基本思路是:在service层创建Connection对象,再将该Connection传给各个DAO类,这样就完成了Connection共享的目的。
修改两个DAO类,使他们都接受一个Connection对象,定义UglyBankDao类如下:
- public class UglyBankDao
- {
- public void withdraw(int bankId, int amount, Connection connection) throws SQLException
- {
- PreparedStatement selectStatement = connection.prepareStatement("SELECT BANK_AMOUNT FROM BANK_ACCOUNT WHERE BANK_ID = ?");
- selectStatement.setInt(1, bankId);
- ResultSet resultSet = selectStatement.executeQuery();
- resultSet.next();
- int previousAmount = resultSet.getInt(1);
- resultSet.close();
- selectStatement.close();
- int newAmount = previousAmount - amount;
- PreparedStatement updateStatement = connection.prepareStatement("UPDATE BANK_ACCOUNT SET BANK_AMOUNT = ? WHERE BANK_ID = ?");
- updateStatement.setInt(1, newAmount);
- updateStatement.setInt(2, bankId);
- updateStatement.execute();
- updateStatement.close();
- }
- }
使用同样的方法,定义UglyInsuranceDao类:
- public class UglyInsuranceDao
- {
- public void deposit(int insuranceId, int amount, Connection connection) throws SQLException
- {
- PreparedStatement selectStatement = connection.prepareStatement("SELECT INSURANCE_AMOUNT FROM INSURANCE_ACCOUNT WHERE INSURANCE_ID = ?");
- selectStatement.setInt(1, insuranceId);
- ResultSet resultSet = selectStatement.executeQuery();
- resultSet.next();
- int previousAmount = resultSet.getInt(1);
- resultSet.close();
- selectStatement.close();
- int newAmount = previousAmount + amount;
- PreparedStatement updateStatement = connection.prepareStatement("UPDATE INSURANCE_ACCOUNT SET INSURANCE_AMOUNT = ? WHERE INSURANCE_ID = ?");
- updateStatement.setInt(1, newAmount);
- updateStatement.setInt(2, insuranceId);
- updateStatement.execute();
- updateStatement.close();
- }
- }
然后修改Service类,在UglyBankService类的transfer方法中,首先创建一个Connection对象,然后在将该对象依次传给UglyBankDao的withdraw方法和UglyInsuranceDao类的deposit方法,这样service层和DAO层使用相同的Connection对象。定义UglyBankService类如下:
- public class UglyBankService implements BankService
- {
- private DataSource dataSource;
- private UglyBankDao uglyBankDao;
- private UglyInsuranceDao uglyInsuranceDao;
- public UglyBankService(DataSource dataSource)
- {
- this.dataSource = dataSource;
- }
- public void transfer(int fromId, int toId, int amount)
- {
- Connection connection = null;
- try
- {
- connection = dataSource.getConnection();
- connection.setAutoCommit(false);
- uglyBankDao.withdraw(fromId, amount, connection);
- uglyInsuranceDao.deposit(toId, amount, connection);
- connection.commit();
- } catch (Exception e)
- {
- try
- {
- assert connection != null;
- connection.rollback();
- } catch (SQLException e1)
- {
- e1.printStackTrace();
- }
- } finally
- {
- try
- {
- assert connection != null;
- connection.close();
- } catch (SQLException e)
- {
- e.printStackTrace();
- }
- }
- }
- public void setUglyBankDao(UglyBankDao uglyBankDao)
- {
- this.uglyBankDao = uglyBankDao;
- }
- public void setUglyInsuranceDao(UglyInsuranceDao uglyInsuranceDao)
- {
- this.uglyInsuranceDao = uglyInsuranceDao;
- }
- }
通过上面共享Connection对象的方法虽然可以完成事务处理的目的,但是这样做法是丑陋的,原因在于:为了完成事务处理的目的,我们需要将一个底层的Connection类在service层和DAO层之间进行传递,而DAO层的方法也要接受这个Connection对象,这种做法显然是不好的,这就是典型的API污染。
在下一篇博文中,我们将讲到如何在不传递Connection对象的情况下完成和本文相同的事务处理功能。
转载地址:http://www.davenkin.me/post/2013-02-22/40049367747
- java事务全解析(三)--丑陋的案例
- Java事务处理全解析(三)——丑陋的案例
- Java事务处理全解析(三)—— 丑陋的案例
- Java事务处理全解析(三)—— 丑陋的案例
- Java事务处理全解析(三)—— 丑陋的案例
- Java事务处理全解析(三)—— 丑陋的案例
- java事务学习笔记(三)--丑陋的案例
- Java事务之三——丑陋的案例
- Java事务(3)——丑陋的案例
- java事务全解析(二)--失败的案例
- java事务全解析(四)--成功的案例(自己实现一个线程安全的TransactionManager)
- Java中事务的处理全解析
- java事务全解析(一)--Java事务处理的基本问题
- java事务全解析(五)--Template模式
- 那些丑陋的Java API
- Java事务处理全解析(二)——失败的案例
- Java事务处理全解析(二)—— 失败的案例
- Java事务处理全解析(二)—— 失败的案例
- dubbo服务端之netty
- C语言字符串的另类用法
- 拆分系统开发 拆分盘模式
- iOS之开发编码规范
- Mybatis 主键配置
- java事务全解析(三)--丑陋的案例
- hdu4652 概率dp求期望
- linux命令总结(不断更新)
- iOS 十六进制和十进制相互转换
- iOS获取网页的标题,内容,节点值
- How to Install Appium on Ubuntu
- 分页(完整版)
- Bag of words模型简介
- 【PAT B1019/A1069】数字黑洞