当一个租赁系统在租房服务时我们会判断用户的账户金额是否够支付本次的房费,如果钱够则扣款,在订单表插入一条本次业务相关的数据,这时候如果在订单表插入出现了异常,但是钱已经扣款成功了,这样的情况就可以加入事务回滚。
事务回滚将本次的操作都使用同一个Connection进行操作,于是加入了ThreadLocal存放Connection
在获取Connection时先看一下当前ThreadLocal是否存放有Connection,如果有则直接从里面获取,没有的话就创建一个Connection并将其放入ThreadLocal中,本次业务中就直接往里取。
private static ThreadLocal threadLocal = new ThreadLocal();
public static Connection getConnection(){
try {
//在ThreadLocal获取Connection
conn = (Connection) threadLocal.get();
//如果没有获取到则进入
if (conn==null){
conn = DriverManager.getConnection(url, user, password);
//将新建的Connection保存到ThreadLocal中
threadLocal.set(conn);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return conn;
}
销毁时则是下图调用closeAll时将Connection传进去。
public static void closeAll(Connection conn, Statement st, ResultSet rs) {
try {
if (rs != null){
rs.close();
}
if (st != null){
st.close();
}
if (conn != null){
conn.close();
threadLocal.remove();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
将Connection对象设置使用setAutoCommit(false)方法设置手动提交事务,接着进行具体业务的操作,如下判断钱是否够、钱够退款、扣款成功添加订单,底层异常往上抛,如果没有出现异常时就提交事务,出现异常时捕获到则回滚事务,业务结束后调用closeAll把Connection对象关闭,并清除了ThreadLocal里的Connection对象;
Connection conn = DBUtil.getConnection();
try{
conn.setAutoCommit(false);//开始手动提交事务
//具体操作
//判断用户钱是否足够
//钱够则扣款
//扣款成功后添加订单
conn.commit(); //提交事务
}catch (Exception ex){
ex.printStackTrace();
conn.rollback(); //事务回滚
}finally {
DBUtil.closeAll(conn,null,null);
}
因为其他业务处理时也要使用到事务回滚,可将事务回滚部分封装代理模式
package com.bjpwoernode.util;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
public class Agent implements InvocationHandler {
private Object service;
public Agent(Object service){
this.service = service;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
Connection conn = DBUtil.getConnection();
try{
conn.setAutoCommit(false);
result = method.invoke(service,args);
conn.commit();
}catch (Exception ex){
ex.printStackTrace();
conn.rollback();
}finally {
DBUtil.closeAll(conn,null,null);
}
return result;
}
public Object getAgent(){
Object lisi = Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), this);
return lisi;
}
}
package com.bjpwoernode;
import com.bjpwoernode.model.Order;
import com.bjpwoernode.service.rentingHouseService;
import com.bjpwoernode.service.serviceImpl.rentingHouseServiceImpl;
import com.bjpwoernode.util.Agent;
import java.lang.reflect.InvocationHandler;
import java.sql.SQLException;
public class MainTest {
public static void main(String[] args) {
Order order = new Order();
order.setuID(3);
order.sethID(2);
rentingHouseService rentingHouseService = new rentingHouseServiceImpl();
InvocationHandler agentManager = new Agent(rentingHouseService);
rentingHouseService lisi = (rentingHouseService) ((Agent)agentManager).getAgent();
try {
int flag = lisi.rentingHouse(order,1300,2);
if (flag == 1)
System.out.println("租赁成功");
if (flag == 0)
System.out.println("权限不足");
if(flag == -1)
System.out.println("金币不足请充值");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}