Java事务(三) - 使用ThreadLocal
来源:互联网 发布:客户端软件的配置 编辑:程序博客网 时间:2024/05/16 18:22
一. 为什么使用ThreadLocal:
在上一篇博文中, 我们通过传递Connection的方式来控制事务, 这种方法可以达到目的, 但让人看的不爽,
如果涉及到调用多个service, 那我是不是还得从controller层传递Connection?
ThreadLocal的用法见上一篇博客, 该类保证一个类的实例变量在各个线程中都有一份单独的拷贝,
从而不会影响其他线程中的实例变量,所以ThreadLocal可以实现线程范围内数据共享。
二. 如何使用ThreadLocal:
1. 写一个TransactionManager类:
/** * 管理事务 */public class TransactionManager {private static ThreadLocal<Connection> local = new ThreadLocal<Connection>();// 开启事务public static void beginTransaction() throws SQLException {Connection conn = JDBCUtils.getConnection();conn.setAutoCommit(false); // 将连接存入threadLocallocal.set(conn);}// 回滚事务public static void rollback() throws SQLException {Connection conn = local.get();if (conn != null) {conn.rollback();conn.close();// 清空threadLocallocal.remove();}}// 提交事务public static void commit() throws SQLException {Connection conn = local.get();if (conn != null) {conn.commit();// 清空threadLocallocal.remove();}}// 关闭连接public static void close() throws SQLException {Connection conn = local.get();if (conn != null) {conn.close();// 清空threadLocallocal.remove();}}// 获取数据库连接public static Connection getConnection() {return local.get();}}使用ThreadLocal, 确保相同的线程获取到的是同一个连接.
2.修改业务处理类
/** * 业务逻辑层 */public class AccountService {public void transfer(Account outAccount, Account inAccount, int money) throws SQLException {// 开启 事务 TransactionManager.beginTransaction();// 查询两个账户AccountDAO accountDAO = new AccountDAO();outAccount = accountDAO.findAccountById(outAccount.getId());inAccount = accountDAO.findAccountById(inAccount.getId());// 转账 - 修改原账户金额 outAccount.setMoney(outAccount.getMoney() - money);inAccount.setMoney(inAccount.getMoney() + money);try {// 更新账户金额accountDAO.update(outAccount);accountDAO.update(inAccount);// 转账成功, 提交事务TransactionManager.commit();} catch (Exception e) {// 转账失败, 回滚事务TransactionManager.rollback();e.printStackTrace();} finally {// 关闭连接TransactionManager.close();}}}
使用TransactionManager来管理事务, 代码变得更加简洁.
3. 修改Dao类
/** * DAO层: CRUD */public class AccountDAO {// 查询账户public Account findAccountById(int id) throws SQLException {String sql = "select * from account where id = ?";Object[] params = {id};QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());return queryRunner.query(sql, new BeanHandler<Account>(Account.class), params);}// 更新账户public void update(Account account) throws SQLException {String sql = "update account set name = ?, money = ? where id = ?";Object[] params = {account.getName(), account.getMoney(), account.getId()};// 从threadLocal中获取连接, 同一个线程拿到的是同一个连接Connection conn = TransactionManager.getConnection();QueryRunner queryRunner = new QueryRunner();queryRunner.update(conn, sql, params);}}
不需要传递Connection, 直接从TransactionManager中获取连接.
三. 总结:
service和dao都是通过TransactionManager来获取Connection, 同一个线程中, 它们在整个事务处理过程中使用了相同的Connection对象, 所以事务会处理成功, dao中没有接受和业务无关的对象, 消除了api污染, 另外使用TransactionManager来管理事务, 使service层的代码变简洁了.
源码下载: http://download.csdn.net/detail/zdp072/7908261
2 0
- Java事务(三) - 使用ThreadLocal
- JAVA中ThreadLocal使用三
- POJO中使用ThreadLocal实现Java嵌套事务
- 使用ThreadLocal控制事务实现用户转账
- Java ThreadLocal使用浅析
- java中ThreadLocal使用
- Java ThreadLocal使用浅析
- java ThreadLocal的使用
- Java ThreadLocal的使用
- 【Java ThreadLocal的使用】
- Java ThreadLocal的使用
- JAVA Threadlocal 的使用
- Java ThreadLocal的使用
- Java ThreadLocal的使用
- Java ThreadLocal使用浅析
- java ThreadLocal 使用详解
- Java ThreadLocal使用浅析
- Java ThreadLocal使用
- Android View.post(Runnable )
- DirectX 9.0c游戏开发手记之RPG编程自学日志之7: Drawing with DirectX Graphics (用DirectX图形绘图)(第3节)
- 希尔排序
- Java内存分配详解
- ZOJ1708
- Java事务(三) - 使用ThreadLocal
- 归并排序
- 黑马程序员—C语言—数组 && 字符串
- Android消息处理机制
- 计数排序
- jvm内存屏障
- SmartUpload上传下载及文件名和文件内容中文问题
- 分类工作基本完成
- 【C++第十课】---继承中的构造与析构