首页 > 代码库 > 操作订单时出现的事务问题

操作订单时出现的事务问题

今天在操作订单的代码时,控制台总是报出反射方法内部出现问题,debug仔细查找后,确定问题出现在dao层:

下面是我写的具体的订单dao

  • public class OrderDao {
  • QueryRunner qr = new QueryRunner();
  • //当点击意见购买时生成订单即往订单表中插入订单
  • public void addOrder(Order order){
  • //得到数据库连接
  • Connection con = null;
  • try {
  • con = JdbcUtils.getConnection();
  • String sql = "insert into orders values(?,?,?,?,?,?)";
  • //将下单时间转换为SQLdate
  • Timestamp ts = new Timestamp(order.getOrdertime().getTime());
  • Object [] params = {order.getOid(),ts,order.getTotal(),
  • order.getState(),order.getUser().getUid(),order.getAddress()};
  • qr.update(con, sql, params);

} catch (SQLException e) {

  • throw new RuntimeException(e);
  • }finally{
  • try{if(con!=null){con.close();}}catch(SQLException e){throw new RuntimeException(e);}
  • }
  • }
  • //向表单中添加表单项
  • public void addOrderItem(List<OrderItem> orderitem){
  • Connection con = null;
  • try {
  • con = JdbcUtils.getConnection();
  • String sql = "insert into orderitem values(?,?,?,?,?)";
  • Object [][] params = new Object[orderitem.size()][];
  • for(int i=0;i<orderitem.size();i++){
  • OrderItem item = orderitem.get(i);
  • params[i] = new Object[]{item.getIid(),item.getCount(),
  • item.getSubtotal(),item.getOrder().getOid(),
  • item.getBook().getBid()};
  • }
  • qr.batch(con, sql, params);
  • } catch (SQLException e) {
  • throw new RuntimeException(e);
  • }finally{
  • try{if(con!=null){con.close();}catch(SQLException e){throw new RuntimeException(e);}
  • }

}

而在service层上面两个方法是包含在同一个事务中,如下所示:

  • public void addOrder(Order order){
  • OrderDao dao = new OrderDao();
  • try {
  • //开启事务
  • JdbcUtils.beginTransaction();
  • dao.addOrder(order);
  • dao.addOrderItem(order.getOrderitemlist());
  • JdbcUtils.commitTransaction();
  • } catch (SQLException e) {
  • System.out.println("asdf");
  • try {
  • //回滚事务
  • JdbcUtils.rollBack();
  • } catch (SQLException e1) {
  • throw new RuntimeException(e);
  • }
  • throw new RuntimeException(e);
  • }
  • }

如上的红色部分是问题的关键,由于在service层中它两所处在同一个事务,所以其中一个一旦关闭连接,就因为无法正常运行另外一个方法而导致SQL异常,最后的解决办法是,我封装了一个JdbcUtils工具类,它有一个释放链接的方法,会先判断事务是否还在使用连接,如果使用就不关闭,如果不使用,就关闭连接。所以红色出现问题的地方应该改为JdbcUtils.releaseConnection(con);问题解决。

 

-----------------------------------------------------------------------------------------------------

问题二:在表单的servlet层发现当用户在选择同一本书时不会出现问题,而购买多种图书时,就会爆出SQL异常说是同一个key值不能插入多条数据。源码如下:

  • public class OrderServlet extends BaseServlet {
  • public String addOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  • //从购物车中获取订单

Cart cart = (Cart) request.getSession().getAttribute("cart");

  • //封装订单
  • Order order = new Order();
  • order.setOid(CommonUtils.uuid());
  • order.setOrdertime(new Date());
  • order.setTotal(cart.getTotal());
  • order.setState(1);
  • order.setUser((User)request.getSession().getAttribute("user"));
  • //封装订单项
  • Collection<CartItem> col = cart.getCartItems();
  • List<OrderItem> orderItemList = new ArrayList<OrderItem>();
  • ////////////////////////////////
  • ///////////////////////////////
  • for(CartItem ci:col){
  • OrderItem oi = new OrderItem();
  • oi.setBook(ci.getBook());
  • oi.setCount(ci.getCount());
  • oi.setIid(CommonUtils.uuid());
  • oi.setSubtotal(ci.getTotal());
  • oi.setOrder(order);
  • orderItemList.add(oi);
  • }
  • order.setOrderitemlist(orderItemList);
  • //清空购物车
  • cart.clear();
  • //调用service方法
  • orderService os = new orderService();
  • os.addOrder(order);
  • request.setAttribute("order", order);
  • return "f:/item/jsps/order/desc.jsp";
  • }
  • }

debug之后发现,选择多种图书时,购物车中没有问题即session没有问题,而是在添加表单项时,原先的图书种类都变成了同一种,仔细研究才发现将

  • OrderItem oi = new OrderItem();写在了红色的/////出,这就导致每次循环产生的订单项都是同一个,因为这里只产生了一个订单对象,而且是购物车集合中的最后一个,因为每次加载后面的总是会覆盖前面的内容。

操作订单时出现的事务问题