1.首先在数据库当中创建数据库,并且创建它的 实现类

package com.beiwo.epet.entity;

public class Account {
private int id; private String name; private int money; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getMoney() {
return money;
} public void setMoney(int money) {
this.money = money;
} }

2.导入jar包,并且 添加到构建路径

3.在这里采用的是C3P0数据源,并且导入它的固定格式文件c3p0-config.xml

    数据源

package com.beiwo.epet.util;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Util { //C3P0数据源
private static ComboPooledDataSource dataSource=new ComboPooledDataSource(); public static DataSource getDataSource() {
return dataSource;
} public static Connection getConn(){
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
} public static Connection getConn2(){
Connection conn=null; try {
conn=dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
} return conn;
} //释放连接
public static void realease(ResultSet rs,Statement stmt,Connection conn){
try {
if(null!=rs){
rs.close();
}
} catch (Exception e) {
// TODO: handle exception
}
try {
if(null!=stmt){
stmt.close();
}
} catch (Exception e) {
// TODO: handle exception
}
try {
if(null!=conn){
conn.close();
}
} catch (Exception e) {
// TODO: handle exception
}
} }

    

  C3P0的固定格式

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///day05</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
</default-config>
</c3p0-config>

4.定义一个Dao接口(BaseDao)

package com.beiwo.epet.dao;

import com.beiwo.epet.entity.Account;

public interface  AccountDao {

    /**
*
* @param fromName //谁转的
* @param toName // 转给谁
* @param money //转了多少钱
* @throws Exception
*/
public void updateAccount(String fromName,String toName,int money)throws Exception; /**
* 更新信息
* @param account
* @throws Exception
*/
public void updateAccount(Account account)throws Exception; /**
* 获取名字
* @param name
* @return
* @throws Exception
*/
public Account findAccountByName(String name)throws Exception;
}

5.Dao的实现类

package com.beiwo.epet.dao.impl;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler; import com.beiwo.epet.dao.AccountDao;
import com.beiwo.epet.entity.Account;
import com.beiwo.epet.util.C3P0Util;
import com.beiwo.epet.util.TransactionManager; public class AccountDaoImpl implements AccountDao{ @Override
public void updateAccount(String fromName, String toName, int money) throws Exception{
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);
} @Override
public void updateAccount(Account account) throws Exception{
QueryRunner qr=new QueryRunner();
qr.update(TransactionManager.getConnection(),"UPDATE account SET money=? WHERE name=?", account.getMoney(),account.getName());
} @Override
public Account findAccountByName(String name) throws Exception{
QueryRunner qr=new QueryRunner();
return qr.query(TransactionManager.getConnection(),"SELECT * FROM account WHERE name=?",new BeanHandler<Account>(Account.class),name); } }

6.定义一个服务层接口来实现转账功能

package com.beiwo.epet.service;

public interface AccountService {

    public void transfer(String formName,String toName,int money);

}

7.实现服务层接口

package com.beiwo.epet.service.impl;

import com.beiwo.epet.dao.AccountDao;
import com.beiwo.epet.dao.impl.AccountDaoImpl;
import com.beiwo.epet.entity.Account;
import com.beiwo.epet.service.AccountService;
import com.beiwo.epet.util.TransactionManager; public class AccountServiceImpl implements AccountService{ @Override
public void transfer(String formName, String toName, int money) {
AccountDao accountDao=new AccountDaoImpl(); try {
///开始一个事务,start transaction;
//获取转入和转出的账户对象
TransactionManager.startTransaction(); Account fromAccount=accountDao.findAccountByName(formName);
Account toAccount=accountDao.findAccountByName(toName); //修改账户的各自金额
fromAccount.setMoney(fromAccount.getMoney()-money);
toAccount.setMoney(toAccount.getMoney()+money); //完成转账的操作
accountDao.updateAccount(fromAccount);

        //如果没有使用ThreadLocal,那么当我们添加这个异常的时候,下面的代码就不会执行,直接进入异常处理,两个事务要么都执行,要么都不执行
int i=2/0; accountDao.updateAccount(toAccount); TransactionManager.commitTransaction(); } catch (Exception e) {
try {
TransactionManager.rollbackTransaction();;//事务的回滚
} catch (Exception e2) {
e2.printStackTrace();
} }finally{
try {
TransactionManager.close();
} catch (Exception e2) {
e2.printStackTrace();
}
} } }

8.再次过程中我们需要保证Connection是同一个Connection,,所以再定义一个管理类来保证是同一个Connection

package com.beiwo.epet.util;

import java.sql.Connection;

public class TransactionManager {

    private static ThreadLocal<Connection> t1=new ThreadLocal<Connection>();

    //获取连接
public static Connection getConnection(){
Connection conn=t1.get();//从当前线程中取出一个连接
if(null==conn){
conn=C3P0Util.getConn();
t1.set(conn);//把conn对象放入当前线程中去
}
return conn;
} //开始事务
public static void startTransaction(){
try {
Connection conn=getConnection();
conn.setAutoCommit(false);//从当前线程中取出连接,并开始事务
} catch (Exception e) {
e.printStackTrace();
} } //提交事务
public static void commitTransaction(){
try {
Connection conn=getConnection();
conn.commit();
} catch (Exception e) {
e.printStackTrace();
}
} //回滚事务
public static void rollbackTransaction(){
try {
Connection conn=getConnection();
conn.rollback();
} catch (Exception e) {
e.printStackTrace();
} } //关闭连接
public static void close(){
try {
Connection conn=getConnection();
conn.close();
t1.remove();
} catch (Exception e) {
e.printStackTrace();
} } }

9.最后一步就是测试,在此过程中我们没有使用main函数,所以我们自定义一个测试类来测试

package com.beiwo.epet.test;

import org.junit.Test;

import com.beiwo.epet.service.AccountService;
import com.beiwo.epet.service.impl.AccountServiceImpl; public class TestTransfer { @Test
public void test(){
AccountService accountService=new AccountServiceImpl(); accountService.transfer("aaa", "bbb", 100); }
}

数据库中原有的数据如下:

测试之后的结果如下:

Dao跨事务调用实现转账功能的更多相关文章

  1. DAO跨事物调用---转账

    第一步创建实体类:Entity package com.beiwo.epet.entity; public class Account { private int id; private String ...

  2. Atitit java c# php c++ js跨语言调用matlab实现边缘检测等功能attilax总结

    Atitit java c# php c++ js跨语言调用matlab实现边缘检测等功能attilax总结 1.1. 边缘检测的基本方法Canny最常用了1 1.2. 编写matlab边缘检测代码, ...

  3. Jedis的八种调用方式(功能:事务,管道)

        1. packagecom.irwin.redis;     2.       3. importjava.util.Arrays;     4. importjava.util.List; ...

  4. (二十四)JDBC应用的事务管理(转账事例)

    目录 利用 Dbutils 进行事务操作(以转账为例) 转账实现方式(不优雅的方式) ThreadLocal 类 转账实现方式(优雅的方式) 利用 Dbutils 进行事务操作(以转账为例) 我们只在 ...

  5. AJAX跨域调用ASP.NET MVC或者WebAPI服务的解决方案

    问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模板创建一个最简单的ASP.NET Web ...

  6. 使用jsonp跨域调用百度js实现搜索框智能提示,并实现鼠标和键盘对弹出框里候选词的操作【附源码】

    项目中常常用到搜索,特别是导航类的网站.自己做关键字搜索不太现实,直接调用百度的是最好的选择.使用jquery.ajax的jsonp方法可以异域调用到百度的js并拿到返回值,当然$.getScript ...

  7. 跨域调用webapi

    web端跨域调用webapi   在做Web开发中,常常会遇到跨域的问题,到目前为止,已经有非常多的跨域解决方案. 通过自己的研究以及在网上看了一些大神的博客,写了一个Demo 首先新建一个webap ...

  8. jsp+servlet+mysql 实现简单的银行登录转账功能

    jsp+servlet+mysql 实现简单的银行登录转账功能 [前期的准备] html(登录界面),servlet(处理业务逻辑),jsp(主要实现界面),mysql(实现与数据库的简单的交互)先从 ...

  9. 关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案

      作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP.NET Web API编写的服务时,会发生无法访问的情况. 重现方式 使用模 ...

随机推荐

  1. [Tool] github 入手教程

    简单的介绍一下 Github 的基本操作. 主页:https://github.com/ 首先自然是在 GitHub 注册一个帐号了.然后开始正文吧. Git 基本介绍 Git 是属于分布式版本控制系 ...

  2. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(四)

    (四)搭建Website Cloud环境 1安装CONTROLLER主机 在开始安装Web site Cloud之前,读者应该对该服务的拓扑结构有个大概了解. 如图: Controller是非常重要的 ...

  3. 供应链需求调研CheckList

    总体(General) 基本情况 1.    企业地址.邮编.电话.传真,项目联系人等基本资料. 2.    企业经营范围,产品线和主导产品. 3.    企业近几年的产值及销售额. 4.    企业 ...

  4. Connect to the DSP on C6A8168/DM8168/DM8148 using CCS

    转自ti-wiki  这份wiki,我曾经就收藏过,但是没有加以重视,以至于绕了一大圈的ccs开发环境的配置,现在正式收藏于自己的博客中...总结良多啊 Connecting to DSP on C6 ...

  5. 【前端构建】WebPack实例与前端性能优化

    计划把微信的文章也搬一份上来. 这篇主要介绍一下我在玩Webpack过程中的心得.通过实例介绍WebPack的安装,插件使用及加载策略.感受构建工具给前端优化工作带来的便利. 壹 | Fisrt 曾几 ...

  6. Linux安装xwindow图形界面(转载)

    http://jingyan.baidu.com/article/7f766daf42ce984100e1d045.html 1.检查Linux系统是否能够联网. 2.执行命令 yum -y grou ...

  7. 学习笔记 HTTP参数污染注入

    HTTP参数污染注入源于网站对于提交的相同的参数的不同处理方式导致. 例如: www.XX.com/a?key=ab&key=3 如果服务端返回输入key的值,可能会有 一: ab 二:3 三 ...

  8. android 自定义控件——(四)圆形进度条

    ----------------------------------↓↓圆形进度条(源代码下有属性解释)↓↓---------------------------------------------- ...

  9. React Native之 ScrollView介绍和使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  10. 文件缓存(配合JSON数组)

    1.  写入缓存:建立文件夹,把list集合里面的数组转换为JSON数组,存入文件夹2.  读取缓存:把JSON数组从文件夹里面读取出来,然后放入list集合,返回list集合 private fin ...