十六、DBUtils事务使用

要保证QueryRunner操作事务时能够生效就必须要保存调用api时使用的Connection对象是同一个.为了减少代码的耦合性,这里可以使用ThreadLocal类来绑定当前线程的Connection对象.

关于事务的操作以及Connection对象的唯一性操作可以写到一个工具类中

package blog.csdn.net.mchenys.utils;

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 DataSourceUtils {
	// c3p0连接池
	private static ComboPooledDataSource ds = new ComboPooledDataSource();
	// 当前线程关联的数据库连接对象
	private static ThreadLocal<Connection> tl = new ThreadLocal<>();

	/**
	 * 从线程中获取连接
	 * 
	 * @return
	 * @throws SQLException
	 */
	public static Connection getConnection() throws SQLException {
		// 从线程中获取conneciton
		Connection conn = tl.get();
		if (conn == null) {
			conn = ds.getConnection();
			// 和当前线程绑定
			tl.set(conn);
		}
		return conn;
	}

	/**
	 * 取数据源
	 * @return
	 */
	public static DataSource getDataSource() {
		return ds;
	}

	/**
	 * 释放资源
	 * @param st
	 * @param rs
	 */
	public static void closeResource(Statement st, ResultSet rs) {
		closeResultSet(rs);
		closeStatement(st);
	}

	/**
	 * 释放资源
	 * @param conn
	 * @param st
	 * @param rs
	 */
	public static void closeResource(Connection conn, Statement st, ResultSet rs) {
		closeResource(st, rs);
		closeConn(conn);
	}

	/**
	 * 释放 connection
	 * @param conn
	 */
	public static void closeConn(Connection conn) {
		if (conn != null) {
			try {
				conn.close();
				// 和线程解绑
				tl.remove();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}

	/**
	 * 释放 statement 
	 * @param st
	 */
	public static void closeStatement(Statement st) {
		if (st != null) {
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			st = null;
		}
	}

	/**
	 * 释放结果集
	 * @param rs
	 */
	public static void closeResultSet(ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			rs = null;
		}
	}

	/**
	 * 开启事务
	 * @throws SQLException
	 */
	public static void startTransaction() throws SQLException {
		getConnection().setAutoCommit(false);
	}

	/**
	 * 事务提交且释放连接
	 */
	public static void commitAndClose() {
		Connection conn = null;
		try {
			conn = getConnection();
			// 事务提交
			conn.commit();
			// 关闭资源
			conn.close();
			// 解除绑定
			tl.remove();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 事务回滚且释放资源
	 */
	public static void rollbackAndClose() {
		Connection conn = null;
		try {
			conn = getConnection();
			// 事务回滚
			conn.rollback();
			// 关闭资源
			conn.close();
			// 解除版定
			tl.remove();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

下面以添加订单和订单项的操作为例演示下在dbutils下的事务事务使用步骤.

需求:提供一个方法生成一条订单,该订单可以包含有多个订单项,当订单或者订单项添加出错的时候回滚所有操作,必须要等这2个操作都完成才算生成订单成功.

Service层操作

package blog.csdn.net.mchenys.service.impl;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

import blog.csdn.net.mchenys.dao.OrderDao;
import blog.csdn.net.mchenys.dao.impl.OrderDaoImpl;
import blog.csdn.net.mchenys.domain.Order;
import blog.csdn.net.mchenys.domain.OrderItem;
import blog.csdn.net.mchenys.domain.PageBean;
import blog.csdn.net.mchenys.domain.Product;
import blog.csdn.net.mchenys.service.OrderService;
import blog.csdn.net.mchenys.utils.DataSourceUtils;

/**
 * 订单模块
 * 
 * @author mChenys
 *
 */
public class OrderServiceImpl implements OrderService {
        ....

	// 添加订单
	public void add(Order order) throws Exception {
		try {
			// 开启事务
			DataSourceUtils.startTransaction();

			OrderDao dao = new OrderDaoImpl();
			// 添加一条订单记录
			dao.add(order);

			// 添加多条订单项记录
			for (OrderItem item : order.getItems()) {
				dao.addItem(item);
			}
			// 完成事务
			DataSourceUtils.commitAndClose();
		} catch (SQLException e) {
			e.printStackTrace();
			// 回滚事务
			DataSourceUtils.rollbackAndClose();
			throw e;
		}
	}

	....

}

DAO层操作

package blog.csdn.net.mchenys.dao.impl;

import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import blog.csdn.net.mchenys.dao.OrderDao;
import blog.csdn.net.mchenys.domain.Order;
import blog.csdn.net.mchenys.domain.OrderItem;
import blog.csdn.net.mchenys.utils.DataSourceUtils;

public class OrderDaoImpl implements OrderDao {

        ....

	@Override
	public void add(Order order) throws Exception {

		// 手动管理事务则不能通过构造方法传入connection
		QueryRunner qr = new QueryRunner();
		String sql = "insert into orders values(?,?,?,?,?,?,?,?)";
		// connection需要保持同一个.从DataSourceUtils中获取
		qr.update(DataSourceUtils.getConnection(), sql, order.getOid(), order.getOrdertime(), order.getTotal(),
				order.getState(), order.getAddress(), order.getName(), order.getTelephone(), order.getUser().getUid());
	}

	@Override
	public void addItem(OrderItem orderItem) throws Exception {

		// 手动管理事务,connection需要保持同一个.从DataSourceUtils中获取
		QueryRunner qr = new QueryRunner();
		String sql = "insert into orderitem values(?,?,?,?,?)";
		qr.update(DataSourceUtils.getConnection(), sql, orderItem.getItemid(), orderItem.getCount(),
				orderItem.getSubtotal(), orderItem.getProduct().getPid(), orderItem.getOrder().getOid());

	}

	....

}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值