转账示例(四):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其他回滚异常. 传播行为: 所谓事务的传播行为 ...
随机推荐
- 关于hive ,eclipse老是提示加载不到驱动
忙活了好长时间,很纳闷为什么加载不上驱动,驱动包.hive的依赖包.hadoop的依赖包也引入了,各种百度最后: hadoop-2.2.0/share/hadoop/common/hadoop-com ...
- vim编辑器的常见使用功能
Vim是一个类似于vi的著名的功能强大.高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性. 掌握简单的vim命令可以大大提高我们编辑文档效率,在装有vim编辑器的linux系统终端输入vim ...
- Spark数据本地化-->如何达到性能调优的目的
Spark数据本地化-->如何达到性能调优的目的 1.Spark数据的本地化:移动计算,而不是移动数据 2.Spark中的数据本地化级别: TaskSetManager 的 Locality L ...
- PHP文本的读写
<?php $txtPart="test0.txt"; //export $txtPartContent=fopen($txtPart,"r"); //读 ...
- 1081: [SCOI2005]超级格雷码
1081: [SCOI2005]超级格雷码 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 301 Solved: 159[Submit][Statu ...
- docker X509 证书错误的终极解决办法
最近在做Docker相关的东西,发现只要一pull镜像,就出现如下的ERROR x509: certificate signed by unknown authority. 调查后发现,是公司IT把h ...
- 学习ASP.NET MVC(十一)——分页
在这一篇文章中,我们将学习如何在MVC页面中实现分页的方法.分页功能是一个非常实用,常用的功能,当数据量过多的时候,必然要使用分页.在今天这篇文章中,我们学习如果在MVC页面中使用PagedList. ...
- 常见Android面试题及答案(详细整理)
1. 请描述一下Activity 生命周期. 答: 如下图所示.共有七个周期函数,按顺序分别是: onCreate(), onStart(), onRestart(), onResume(), onP ...
- 'utf8' codec can't decode byte 0xd1 in position 931: invalid continuation byte解决方法
有时候,我得到这样的字符œ导致的UnicodeDecodeError错误. 我需要能够使串的UTF-8有或没有这些字符. 在工作中,经常遇到,读取一个文件,或者是从网页获取一个问题,明明看着是gb23 ...
- struct 和typedef struct的区别
和int char一样struct也是一种数据类型,也可以声明变量--结构变量. 定义结构体变量的一般格式为: struct 结构名 { 类型 变量名; 类型 变量名; ... }结构变量; 另一种常 ...