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的固定格式
com.mysql.jdbc.Driver jdbc:mysql:///day05 root root 10 30 100 10
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.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 ThreadLocalt1=new ThreadLocal (); //获取连接 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); }}
数据库中原有的数据如下:
测试之后的结果如下: