转账示例(四):service层面实现(线程管理Connection,AOP思想,动态代理)(本例采用QueryRunner来执行sql语句,数据源为C3P0)
用了AOP(面向切面编程),实现动态代理,service层面隐藏了开启事务。
1.自行创建C3P0Uti,account数据库,导入Jar包
2.Dao层面
接口:
package com.learning.dao;
import com.learning.domain.Account;
public interface AccountDao {
/**
* 转账
* @param fromname 转出用户
* @param toname 转入用户
* @param money 转账金额
*/
@Deprecated
public void updateAccount(String fromname,String toname,double money)throws Exception;
/**
* 根据账户信息修改金额
* @param accout
*/
public void updateAccout(Account accout) throws Exception;
/**
* 根据用户名查找账户信息
* @param name
* @return
* @throws Exception
*/
public Account findAccountByName(String name)throws Exception;
}
实现类:
package com.learning.dao.impl; import java.sql.Connection;
import java.sql.SQLException; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler; import com.learning.dao.AccountDao;
import com.learning.domain.Account;
import com.learning.util.C3P0Util; public class AccountDaoImpl implements AccountDao { private Connection conn; public AccountDaoImpl(Connection conn) {
this.conn = conn;
} public void updateAccount(String fromname, String toname, double money) throws Exception {
//创建一个QueryRunner对象
QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
qr.update("update account set money=money-? where name=?",money,fromname);
qr.update("update account set money=money+? where name=?",money,toname);
} public void updateAccout(Account account) throws Exception {
QueryRunner qr = new QueryRunner();
qr.update(conn,"update account set money=? where name=?",account.getMoney(),account.getName());
} public Account findAccountByName(String name) throws Exception {
QueryRunner qr = new QueryRunner();
return qr.query(conn,"select * from account where name=?", new BeanHandler<Account>(Account.class),name);
} }
3.Service层面
接口:
package com.learning.service;
public interface AccountService {
/**
* 转账
* @param fromname 转出用户
* @param toname 转入用户
* @param money 转账金额
*/
public void transfer(String fromname,String toname,double money);
}
实现类:
package com.learning.service.impl; import java.sql.Connection;
import java.sql.SQLException; import com.learning.dao.AccountDao;
import com.learning.dao.impl.AccountDaoImpl;
import com.learning.domain.Account;
import com.learning.service.AccountService;
import com.learning.util.C3P0Util;
import com.learning.util.ManagerThreadLocal; public class AccountServiceImpl implements AccountService { public void transfer(String fromname, String toname, double money) throws Exception {
// ad.updateAccount(fromname, toname, money);
AccountDao ad = new AccountDaoImpl(); //分别得到转出和转入账户对象
Account fromAccount = ad.findAccountByName(fromname);
Account toAccount = ad.findAccountByName(toname); //修改账户各自的金额
fromAccount.setMoney(fromAccount.getMoney()-money);
toAccount.setMoney(toAccount.getMoney()+money); //完成转账操作
ad.updateAccout(fromAccount);
int i = 10/0;
ad.updateAccout(toAccount); } }
4.创建ManagerThreadLocal管理Connection
AccountDaoImpl();
try {
ManagerThreadLocal.startTransacation();//begin
//分别得到转出和转入账户对象
Account fromAccount = ad.findAccountByName(fromname);
Account toAccount = ad.findAccountByName(toname);
//修改账户各自的金额
fromAccount.setMoney(fromAccount.getMoney()-money);
toAccount.setMoney(toAccount.getMoney()+money);
//完成转账操作
ad.updateAccout(fromAccount);
// int i = 10/0;
ad.updateAccout(toAccount);
ManagerThreadLocal.commit();//提交事务
} catch (Exception e) {
try {
ManagerThreadLocal.rollback();//回滚事务
} catch (Exception e1) {
e1.printStackTrace();
}
}finally{
try {
ManagerThreadLocal.close();
} catch (Exception e) {
e.printStackTrace();
}//关闭
}
}package com.learning.util;
import java.sql.Connection;
import java.sql.SQLException;
public class ManagerThreadLocal {
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
//得到一个连接
public static Connection getConnection(){
Connection conn = tl.get();//从当前线程中取出一个连接
if(conn==null){
conn = C3P0Util.getConnection();//从池中取出一个
tl.set(conn);//把conn对象放入到当前线程对象中
}
return conn;
}
//开始事务
public static void startTransacation(){
try {
Connection conn = getConnection();
conn.setAutoCommit(false);//从当前线程对象中取出的连接,并开始事务
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void commit(){
try {
getConnection().commit();//提交事务
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void rollback(){
try {
getConnection().rollback();//回滚事务
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(){
try {
getConnection().close();//把连接放回池中
tl.remove();//把当前线程对象中的conn移除
} catch (SQLException e) {
e.printStackTrace();
}
}
}
5.创建ProxyFactory(代理类)
package com.learning.util; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import com.learning.service.AccountService;
import com.learning.service.impl.AccountServiceImpl; public class ProxyFactory {
//方法返回一个代理对象
public static AccountService getAccountService(){
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 invoke = null;
try { ManagerThreadLocal.startTransacation();//begin
//执行的是真实对象的转账方法
invoke = method.invoke(as, args); ManagerThreadLocal.commit();//提交事务
} catch (Exception e) {
try {
ManagerThreadLocal.rollback();//回滚事务
} catch (Exception e1) {
e1.printStackTrace();
}
}finally{
try {
ManagerThreadLocal.close();
} catch (Exception e) {
e.printStackTrace();
}//关闭
}
return invoke;
}
});
return proxy;
}
}
6.Test
package com.learning.test; import com.learning.service.AccountService;
import com.learning.service.impl.AccountServiceImpl;
import com.learning.util.ObjectFactory; public class TestTransfer { /**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
AccountService as = ProxyFactory.getAccountService();
as.transfer("aaa", "bbb", 100);
} }
转账示例(四):service层面实现(线程管理Connection,AOP思想,动态代理)(本例采用QueryRunner来执行sql语句,数据源为C3P0)的更多相关文章
- 转账示例(三):service层面实现(线程管理Connection)(本例采用QueryRunner来执行sql语句,数据源为C3P0)
缺点:Service层面还是不应该出现关于事务的操作1.自行创建C3P0Uti,account数据库,导入Jar包 2.Dao层面 接口: package com.learning.dao; impo ...
- 转账示例(二):service层面实现(本例采用QueryRunner来执行sql语句,数据源为C3P0)
缺点:Service层面把Dao层面的开启事务操作完成了1.自行创建C3P0Uti,account数据库,导入Jar包 2.Dao层面 接口: package com.learning.dao; im ...
- 转账示例(一):Dao层面实现(本例采用QueryRunner来执行sql语句,数据源为C3P0)
缺点:Dao层面把Service层面的操作完成了,不利于后期的代码修改和重构 1.自行创建C3P0Util account数据库 2.jar包 3.Dao层面 接口: package com.lear ...
- 在EF4.1的DBContext中实现事务处理(BeginTransaction)和直接执行SQL语句的示例
在EF4.1的DBContext中实现事务处理(BeginTransaction)和直接执行SQL语句的示例 (2012-03-13 10:12:48) 转载▼ public ActionResu ...
- JDBC详解系列(四)之建立Stament和执行SQL语句
建立Stament 在获得连接之后,我们就可以跟数据库进行交互了. 在JDBC中,我们发送SQL语句到数据库这些操作时通过Stament,Preparement,CallableStateme ...
- ucore操作系统学习(四) ucore lab4内核线程管理
1. ucore lab4介绍 什么是进程? 现代操作系统为了满足人们对于多道编程的需求,希望在计算机系统上能并发的同时运行多个程序,且彼此间互相不干扰.当一个程序受制于等待I/O完成等事件时,可以让 ...
- Java--简单的Spring AOP配置以及AOP事物管理,JDK/GCLib动态代理
一.看一下简单的通过XML的AOP配置 1.首先创建一个简单的Student类 public class Student { private Integer age; private String n ...
- SpringBoot | 第二十四章:日志管理之AOP统一日志
前言 上一章节,介绍了目前开发中常见的log4j2及logback日志框架的整合知识.在很多时候,我们在开发一个系统时,不管出于何种考虑,比如是审计要求,或者防抵赖,还是保留操作痕迹的角度,一般都会有 ...
- Spring学习8-Spring事务管理(AOP/声明式式事务管理)
一.基础知识普及 声明式事务的事务属性: 一:传播行为 二:隔离级别 三:只读提示 四:事务超时间隔 五:异常:指定除去RuntimeException其他回滚异常. 传播行为: 所谓事务的传播行为 ...
随机推荐
- mysql view视图的简单使用....
为什么使用视图 1.查询性能提高. 2.安全 3.有灵活性的功能需求后,需要改动表的结构而导致工作量比较大.那么可以使用虚拟表的形式达到少修改的效果 4.复杂的查询需求.可以进行问题分解,然后将创建多 ...
- 裸机(Bare Metal)安装CoreOS
本文以 1235.9.0-stable 为例,在WMWare中进行安装. 1.获取安装资源 https://coreos.com/releases/ 通过"Browse Images&quo ...
- PCB行业版特色功能展示
普实PCB行业版,专为PCB行业需求而定制.秉承一体化.集团化.移动化为设计理念,采用互联网技术.云计算技术.移动应用技术开发的新一代系统帮助PCB企业创新管理模式.引领商业变革!系统从接到订单开始, ...
- smarty模板做人员表信息删除,修改 里面的性别单选按钮民族下拉,另外登录进去可以显示姓名
首先登录进去可以显示姓名 smarty模板做人员表信息删除,删除的时候有提示框确定删除吗. 修改 里面的性别单选按钮,要修改谁有默认选中,用了变量调节器 民族位置做下拉,用<{foreach}& ...
- Oracle Jdbc驱动下载及安装本地maven仓库
由于二进制许可 binary license的限制,oracle jdbc驱动不能通过共有仓库来获取,所以你可以下载下来添加到自己的本地仓库或私有仓库中. 添加到本地仓库步骤如下: 下载Oracle ...
- 解决AJAX在火狐,谷歌都能正常运行,而IE不行的问题
如图所示: 经过一系列测试,并不是data参数的问题,也不是if...else...判断的问题,居然是console.log()将函数阻拦住了,百度了下说低版本的IE不支持console.log(), ...
- js中call、apply、bind那些事
前言 回想起之前的一些面试,几乎每次都会问到一个js中关于call.apply.bind的问题,比如- 怎么利用call.apply来求一个数组中最大或者最小值 如何利用call.apply来做继承 ...
- hdoj1242(dfs 剪枝 解法)
题意:拯救行动,天使r有多个朋友a(friends,在这里被坑了几次,没看清题意),天使被关在牢房里,等着朋友来拯救,求拯救天使的最短距离. 解法:如果不剪枝,200*200的地图会超时,可以以天使为 ...
- 双系统删除Ubuntu后出现grub界面而无法正常启动Windows系统的解决方法
第一次安装双系统的时候由于不怎么会弄,设置了ubuntu引导windows,这种方法是非常不推荐的,因为当ubuntu出现问题或者是当你不再使用ubuntu的时候,删除ubuntu就会成为一个很麻烦的 ...
- MySQL基准测试(benchmark)
基准测试是唯一方便有效的.可以学习系统在给定的工作负载下会发生什么的方法.基准测试可以观察系统在不同压力下的行为,评估系统的容量,掌握哪些是重要的变化,或者观察系统如何处理不同的数据. 验证基于系统的 ...