• Dao跨事务调用实现转账功能


    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);
            
        }
    }
    

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

    测试之后的结果如下:

  • 相关阅读:
    【转】Elasticsearch 聚合数据结果不精确,怎么破?
    C# ling to sql group by分组查询
    c# JArray将返回json字符串集合 转为集合
    .netcore 获取请求客户端IP
    IP转long与string相互转化方法
    C# 操作datatable校验重复行,并显示行号
    springboot 以多模块形式集成Dubbo部署RPC服务
    windows 下搭建dubbo环境搭建
    spring 创建多模块项目,找不到jar包
    使用ZKUI Web页面管理zookeeper
  • 原文地址:https://www.cnblogs.com/houjiie/p/6196197.html
Copyright © 2020-2023  润新知