转账示例:service层面实现(线程管理Connection,AOP思想,动态代理)(本例采用QueryRunner来执行sql语句,数据源为C3P0)

Posted 第九种格调的人生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转账示例: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层面实现(本例采用QueryRunner来执行sql语句,数据源为C3P0)

转账示例:Dao层面实现(本例采用QueryRunner来执行sql语句,数据源为C3P0)

线程与进程(续)

多线程转账代码示例

用python实现银行转账功能

阶段3 2.Spring_07.银行转账案例_4 编写事务管理工具类并分析连接和线程解绑