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

时间:2021-04-01 01:00:10

缺点: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();
}
}
}