Treadlocal的实现转账思想解读MVC
2016-09-23 17:23
225 查看
一、ThreadLocal是默认使用当前线程作为键(key)
其实现原理如下:
准备工作:
domain中有属性:int id;String name;int price
导入C3P0等各种包及对应的工具类
二、用普通的方法实现转账功能
注:要保证使用的是同一个Connection对象
1、dao实现层
2、service业务实现层
三、用ThreadLocal实现转账功能
1、dao层仅仅处理与数据库增删改查相关的sql语句,AccountDaoImpl代码实现如下:
2.service层负责具体的业务逻辑,AccountServiceImpl层实现如下:
编写测试类:
dao中QueryRunner实现时如果没有传入数据源对象,而在query方法传入数据源对象,属于手动控制事务,例如转账这种特殊的业务需求,要用到ThreadLocal,即:多条sql语句的操作必须在同一个事务中,使用同一个Connection对象进行控制。否则两条执行的事务中间如果发生异常,第一个事务执行后第二个事务不会继续执行。
四、用代理实现-终极优化
为了使service层更加专注于业务处理,我们用此处使用代理。
新建工具类AccountServiceFactory
//得到转账人的信息
Account from = accountDao.findAccountByName(fromname);
//得到收钱人的信息
Account to = accountDao.findAccountByName(toname);
from.setMoney(from.getMoney()-money);
to.setMoney(to.getMoney()+money);
//转账
accountDao.updateAccount(from);
//int num = 5/0;
accountDao.updateAccount(to);在主函数中调用代理
AccountService proxy=AccountServiceFactory.getAccountServiceProxy();
proxy.transfer("lisi", "zhaosi", 100);
附:工具类下的ManagerThreadLocal
其实现原理如下:
public class ThreadLocal{ private Map<Runnable,Object> container = new HashMap<Runnable,Object>(); public void set(Object value){ container.put(Thread.currentThread(),value);//用当前线程作为key } public Object get(){ return container.get(Thread.currentThread()); } public void remove(){ container.remove(Thread.currentThread()); }
准备工作:
domain中有属性:int id;String name;int price
导入C3P0等各种包及对应的工具类
二、用普通的方法实现转账功能
注:要保证使用的是同一个Connection对象
1、dao实现层
private Connection conn; public AccountDaoImpl(Connection conn) { this.conn = conn; } /** * 更新账户余额的功能 */ public void updateAccount(Account account) throws SQLException { QueryRunner qr = new QueryRunner(); qr.update(conn, "update account set money=? where name=?", account.getMoney(), account.getName()); } /** * 根据用户名查询用户信息的功能 */ public Account findAccountByName(String name) throws SQLException { QueryRunner qr = new QueryRunner(); // 返回一个Accout对象 return qr.query(conn, "select * from account where name=?", new BeanHandler<Account>(Account.class), name); }
2、service业务实现层
private AccountDao accountDao; public void transfer(String fromname, String toname, int money) { Connection conn = null; try { //注:一个sql语句就是一个事务,要把两个事务放在一起 conn = C3P0Util.getConnection(); //设置AccountDaoImpl使用的也是 这个conn accountDao = new AccountDaoImpl(conn); conn.setAutoCommit(false); //得到转账人的信息 Account from = accountDao.findAccountByName(fromname); //得到收钱人的信息 Account to = accountDao.findAccountByName(toname); from.setMoney(from.getMoney()-money); to.setMoney(to.getMoney()+money); //转账--更新 accountDao.updateAccount(from); int num = 5/0; accountDao.updateAccount(to); conn.commit(); } catch (Exception e) { try { conn.rollback(); e.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } }
三、用ThreadLocal实现转账功能
1、dao层仅仅处理与数据库增删改查相关的sql语句,AccountDaoImpl代码实现如下:
/** * 更新账户余额的功能 */ public void updateAccount(Account account) throws SQLException { QueryRunner qr = new QueryRunner(); qr.update(ManagerThreadLocal.getConnection(),"update account set money=? where name=?", account.getMoney(),account.getName()); } /** * 根据用户名查询用户信息的功能 */ public Account findAccountByName(String name) throws SQLException { QueryRunner qr = new QueryRunner(); return qr.query(ManagerThreadLocal.getConnection(),"select * from account where name=?", new BeanHandler<Account>(Account.class),name); } }
2.service层负责具体的业务逻辑,AccountServiceImpl层实现如下:
private AccountDao accountDao = new AccountDaoImpl(); public void transfer(String fromname, String toname, int money) { try { //注:一个sql语句就是一个事务,要把两个事务放在一起 //需要手动控制事务则是service 先得到Connection对象,否则是Dao先得到 Connection对象 ManagerThreadLocal.startTransaction(); //得到转账人的信息 Account from = accountDao.findAccountByName(fromname); //得到收钱人的信息 Account to = accountDao.findAccountByName(toname); from.setMoney(from.getMoney()-money); to.setMoney(to.getMoney()+money); //转账 accountDao.updateAccount(from); //int num = 5/0; accountDao.updateAccount(to); ManagerThreadLocal.commitTrancsaction(); } catch (Exception e) { try { //有异常回滚事务 e.printStackTrace(); ManagerThreadLocal.roolBackTransaction(); } catch (SQLException e1) { e1.printStackTrace(); } }finally{ try { //最后关闭资源 ManagerThreadLocal.close(); } catch (SQLException e) { e.printStackTrace(); } } }
编写测试类:
AccountService accountService = new AccountServiceImpl(); accountService.transfer("王健健", "王思思", 100);dao中QueryRunner实现时如果传入数据源对象(C3P0Util.getDataSource),属于自动控制事务。
dao中QueryRunner实现时如果没有传入数据源对象,而在query方法传入数据源对象,属于手动控制事务,例如转账这种特殊的业务需求,要用到ThreadLocal,即:多条sql语句的操作必须在同一个事务中,使用同一个Connection对象进行控制。否则两条执行的事务中间如果发生异常,第一个事务执行后第二个事务不会继续执行。
四、用代理实现-终极优化
为了使service层更加专注于业务处理,我们用此处使用代理。
新建工具类AccountServiceFactory
package com.zgf.util; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.SQLException; import com.qianfeng.service.AccountService; import com.qianfeng.service.impl.AccountServiceImpl; //创建AccountService代理对象的工厂类 public class AccountServiceFactory { public static AccountService getAccountServiceProxy() { final AccountService as=new AccountServiceImpl();//被代理的对象 AccountService proxy=(AccountService) Proxy.newProxyInstance(as.getClass().getClassLoader(), as.getClass().getInterfaces(), new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj=null; try { //注:一个sql语句就是一个事务,要把两个事务放在一起 ManagerThreadLocal.startTransaction(); //代理执行transfer 代理的就是他 obj=method.invoke(as,args);//没有参数 ManagerThreadLocal.commitTrancsaction(); } catch (Exception e) { try { //有异常回滚事务 e.printStackTrace(); ManagerThreadLocal.roolBackTransaction(); } catch (SQLException e1) { e1.printStackTrace(); } }finally{ try { //最后关闭资源 ManagerThreadLocal.close(); } catch (SQLException e) { e.printStackTrace(); } } return obj; } }); return proxy; } }这样在service实现层就可以简单的纯粹的业务处理
//得到转账人的信息
Account from = accountDao.findAccountByName(fromname);
//得到收钱人的信息
Account to = accountDao.findAccountByName(toname);
from.setMoney(from.getMoney()-money);
to.setMoney(to.getMoney()+money);
//转账
accountDao.updateAccount(from);
//int num = 5/0;
accountDao.updateAccount(to);在主函数中调用代理
AccountService proxy=AccountServiceFactory.getAccountServiceProxy();
proxy.transfer("lisi", "zhaosi", 100);
附:工具类下的ManagerThreadLocal
package com.zgf.util; import java.sql.Connection; import java.sql.SQLException; public class ManagerThreadLocal { private static ThreadLocal<Connection> local = new ThreadLocal<Connection>(); public static Connection getConnection() throws SQLException { Connection conn = null; conn = local.get();//从ThreadLocal中获取Connection 对象 if(conn==null){ conn = C3P0Util.getConnection(); local.set(conn);//把取到的Connection对象 放入ThreadLocal } return conn; } //开启事务 public static void startTransaction() throws SQLException { Connection conn = getConnection(); conn.setAutoCommit(false); } //提交事务 public static void commitTrancsaction() throws SQLException { getConnection().commit(); } //回滚事务 public static void roolBackTransaction() throws SQLException { getConnection().rollback(); } public static void close() throws SQLException { getConnection().close();//放回连接池 local.remove();//从ThreadLocal中删除 } }
相关文章推荐
- 简述MVC思想与PHP如何实现MVC
- php中实现MVC的思想
- ASP.NET MVC 简单的分页思想与实现
- MVC 编程思想实例 (基于java,jdbc操作mysql数据库实现登陆注册)
- SpringMVC+freemarker实现菜单导航的思想一
- 简述MVC思想与PHP如何实现MVC
- MVC思想实现一个 Android 的GridView
- ASP.NET MVC 简单的分页思想与实现
- 简述MVC思想 与PHP如何实现MVC
- MVC思想在PHP中的实现思路
- php中实现MVC的思想
- ASP.NET MVC 简单的分页思想与实现
- 用java实现一个单线程基于控制台和以文件为数据存储并加上一点MVC思想的ATM
- 2.1、Spring Web MVC是什么 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职
- 简述MVC思想与PHP如何实现MVC
- 简述MVC思想与PHP如何实现MVC(转)
- 结合Java实现的一个腾讯空间备份器谈谈MVC思想在Swing桌面项目中的应用
- 用jsp+servlet+jdbc实现登录功能(体现mvc设计思想)
- web MVC 思想模式解读(图示)
- javaWeb的MVC思想解读