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

缺点: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) {
    //    ad.updateAccount(fromname, toname, money);
        AccountDao ad = new 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();
            }//关闭
        }
    }

}

4.创建ManagerThreadLocal管理Connection

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();
        }
    }
}
时间: 2024-11-06 10:36:03

转账示例(三):service层面实现(线程管理Connection)(本例采用QueryRunner来执行sql语句,数据源为C3P0)的相关文章

转账示例(四):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 转账金额 */

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

缺点:Service层面把Dao层面的开启事务操作完成了 1.自行创建C3P0Uti,account数据库,导入Jar包 2.Dao层面 接口: package com.learning.dao; import com.learning.domain.Account; public interface AccountDao { /** * 转账 * @param fromname 转出用户 * @param toname 转入用户 * @param money 转账金额 */ @Deprecat

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

缺点:Dao层面把Service层面的操作完成了,不利于后期的代码修改和重构 1.自行创建C3P0Util account数据库 2.jar包 3.Dao层面 接口: package com.learning.dao; import com.learning.domain.Account; public interface AccountDao { /** * 转账 * @param fromname 转出用户 * @param toname 转入用户 * @param money 转账金额 *

PDO中执行SQL语句的三种方法

在PDO中,我们可以使用三种方式来执行SQL语句,分别是 exec()方法,query方法,以及预处理语句prepare()和execute()方法~大理石构件来图加工 在上一篇文章<使用PDO构造函数连接数据库及DSN详解>中,我们介绍了如何使用构造函数连接数据库和DSN的详解,那么我们这篇文章跟大家介绍在PDO中执行SQL语句的三种方式,下面我们将一一介绍! 第一种方法:exec()方法 exec()方法返回执行SQL 语句后受影响的行数,其语法格式如下: 1 int PDO::exec(

测开之路一百三十八:会话管理之session

session管理和使用,需要用到flask的session模块和设置安全码:app.secret_key 比如列表页和编辑功能只能给admin用 列表页 编辑页 添加session 登录成功时,把username添加到session里面 app.secret_key = 'qoihf2397r21380r2/./ad' # 加密的安全码,越复杂越好,flask后台自动进行加密 @app.route('/login/', methods=['GET', 'POST'])def login():

《Entity Framework 6 Recipes》中文翻译系列 (12) -----第三章 查询之使用SQL语句 (转)

3-2使用原生SQL语句更新 问题 你想在实体框架中使用原生的SQL语句,来更新底层数据存储. 解决方案 假设你有一张如图3-2所示的Payment数据库表,使用实体框架设计器工具创建了一个如图3-2所示的模型. 图3-2 Payment表,包含一个供应商的付款信息 图3-3 包含一个Payment实体的模型 为了在底层的Payment表中执行一句和多句SQL语句,可以使用在DbContext类中的属性Database中的ExecuteSQlCommand()方法. 虽然我们能在模型中查询Pay

C#与数据库访问技术总结(六)之Command对象创建SQl语句代码示例

Command对象创建SQl语句代码示例 说明:前面介绍了 Command 对象的方法和一些属性,回顾一下 Command对象主要用来执行SQL语句.利用Command对象,可以查询数据和修改数据. 在下面这段代码里,首先根据连接字符串创建一个SqlConnecdon连接对象,并用此对象连接数据源:然后创建一个SqlCommand对象,并用此对象的ExecuteNonQuery方法执行不带返回结果集的SQL语句. 1 //连接字符串 2 3 private static string strCo

Android线程管理之ThreadPoolExecutor自定义线程池(三)

前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己来自定义一个线程池,今天来学习一下ThreadPoolExecutor,然后结合使用场景定义一个按照线程优先级来执行的任务的线程池. ThreadPoolExecutor ThreadPoolExecutor线程池用于管理线程任务队列.若干个线程. 1.)ThreadPoolExecutor构造函数

Android线程管理(三)——Thread类的内部原理、休眠及唤醒

线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用.本小节主要从以下三个方面进行分析: <Android线程管理(一)——线程通信> < Android线程管理(二)——ActivityThread > < Android线程管理(三)——Thread类的内部原理.休眠及唤醒 > 三.Thread类的内部原理.休眠及唤醒 3