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);
}
}
数据库中原有的数据如下:
测试之后的结果如下: