18_生成订单

生成订单

  • 需求与步骤分析
  • 准备工作

1)需求与步骤分析

需求分析:
在购物车页面上,有一个提交订单按钮,点击的时候将用户购物车中的商品添加到数据库中
实体:
用户
订单
订单项
商品
我们在第一章分析时已经分析过了他们的关系:
在这里插入图片描述
步骤分析:

  • 点击生成订单:${path}/order/add
  • 创建OrderServlet:
    • 处理add,创建add方法。1. 判断用户是否登录,2. 封装数据Order
    • 调用orderService生成订单。1. 向订单表中插入一条数据,2. 向订单项表中插入多条数据
      要么成功,要么失败,所以要使用事务控制

2)准备工作

① 创建数据表

在这里插入图片描述

② 创建实体类

订单实体Order:

public class Order implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = -8541282704453921798L;	
	private String oid;
	/**
	 * 下单时间
	 */
	private Date ordertime;
	/**
	 * 总价
	 */
	private Double total;
	/**
	 * 状态 0 未支付,1 已支付 2 
	 */
	private Integer state;
	/**
	 * 订单收件地址
	 */
	private String address;
	/**
	 * 收件人
	 */
	private String name;
	/**
	 * 收件号码
	 */
	private String telephone;
	/**
	 * 属于哪个用户
	 */
	private User user;
	/**
	 * 一个订单包含多个订单项
	 */
	private List<OrderItem> items=new ArrayList<>();
	
	//getter和setter...	
}

订单项实体OrderItem:

public class OrderItem implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = -2760996836863504723L;
	/**
	 * 订单项id
	 */
	private String itemid;
	/**
	 * 订单项商品总数量
	 */
	private Integer count;
	/**
	 * 当前订单项金额
	 */
	private Double subtotal;
	/**
	 * 包含哪个实体
	 */
	private Product product;
	/**
	 * 属于哪个订单
	 */
	private Order order;
	//getter和setter...
}
③ 创建Order与OrderItem的dao层和service层接口和实现类

略:


3)代码实现

① 编写CardServlet处理add,生成订单
	/**
	 * 生成订单
	 * @param request
	 * @param response
	 * @throws IOException 
	 * @throws ServletException 
	 */
	private void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1、判断用户是否登录
		User user=(User) request.getSession().getAttribute("user");
		if(user == null) {
			request.setAttribute("msg", "请先登录~~");
			request.getRequestDispatcher("/jsp/msg.jsp").forward(request, response);
			return;
		}
		
		//2、封装数据
		Order order=new Order();
		
		//2.1 订单id
		order.setOid(UUIDUtils.getId());
		
		//2.2 订单时间
		order.setOrdertime(new Date());
		
		//2.3 总金额
		//获取session中的cart
		Cart cart=(Cart) request.getSession().getAttribute("cart");
		order.setTotal(cart.getTotal());
		
		//2.4 订单的所有订单项
		/*
		 * 先获取cart中的items
		 * 遍历items 组装成orderItem
		 * 将orderItem添加到list(itmes)中
		 */
		for(CartItem cartItem:cart.getItems()) {
			//创建订单项
			OrderItem orderItem=new OrderItem();
			//2.4.1 设置订单项id
			orderItem.setItemid(UUIDUtils.getId());
			//2.4.2 设置购买数量
			orderItem.setCount(cartItem.getCount());
			//2.4.3 设置小计
			orderItem.setSubtotal(cartItem.getSubtotal());
			//2.4.5 设置商品
			orderItem.setProduct(cartItem.getProduct());
			//2.4.6 设置order
			orderItem.setOrder(order);
			//2.4.7 添加到list
			order.getItems().add(orderItem);
			
		}
		//2.5 设置用户
		order.setUser(user);
		//3、调用service 添加订单
		orderService.add(order);
		//4、将order绑定到request中,请求转发到/jsp/order_info.jsp
		request.setAttribute("order", order);
		request.getRequestDispatcher("/jsp/order_info.jsp").forward(request, response);
	}
② 更改DBUtil,提供操作事务控制的方法

开启事务方法:

	/**
	 * 开启事务
	 */
	public static void startTransaction() {
		try {
			getConnection().setAutoCommit(false);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

事务提交并释放资源:

	/**
	 * 事务提交并关闭
	 */
	public static void commitAndClose() {
		Connection connection = getConnection();
		try {
			connection.commit();
			connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

事务回滚并释放资源:

	/**
	 * 事务回滚并关闭
	 */
	public static void rollbackAndClose() {
		Connection connection = getConnection();
		try {
			connection.rollback();
			connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
③ 在service层生成订单,使用事务控制
	@Override
	public void add(Order order) throws Exception{
		try {
			//1、开启事务
			DBUtil.startTransaction();
			//2、向orders表中添加一条记录
			orderDao.add(order);
			//3、向orderitem表中添加多条记录
			for(OrderItem orderItem:order.getItems()) {
				orderDao.addItem(orderItem);
			}
			//4、事务处理
			DBUtil.commitAndClose();
		}catch(Exception e) {
			e.printStackTrace();
			//错误回滚
			DBUtil.rollbackAndClose();
			throw e;
		}
	}
④ 在dao层实现增加
	public class OrderDaoImpl implements OrderDao{
		//QueryRunner
		private QueryRunner qr=new QueryRunner(DBUtil.getDataSource());
		@Override
		public void add(Order order) throws SQLException {
			String sql="insert into `orders` values(?,?,?,?,?,?,?,?)";
			qr.update(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 SQLException {
			String sql="insert into `orderitem` values(?,?,?,?,?)";
			qr.update(sql,orderItem.getItemid(),orderItem.getCount(),orderItem.getSubtotal()
					,orderItem.getProduct().getPid(),orderItem.getOrder().getOid());
		}
	}
⑤ 先测试事务

先把商品加入购物车,点击提交订单:
在这里插入图片描述

查看数据库是否添加成功:
订单表:
在这里插入图片描述
订单项表:
在这里插入图片描述
修改service,手动添加异常测试事务回滚:

	...
	//2、向orders表中添加一条记录
	orderDao.add(order);
	
	int a=1/0;
	
	//3、向orderitem表中添加多条记录
	...

再进行测试:
在这里插入图片描述
提交订单,查看数据库:
在这里插入图片描述
增加成功,事务并没有回滚!!!把这个没有任何关联的数据删除掉
原因:因为在dao层执行的时候时重新获取的Connection,跟Service层处理事务时用的不是同一个连接,当然不会成功

先修改DBUtil的getConnection方法从线程池中获取
	//1、定义一个连接池
	private static BasicDataSource ds;
	//2、定义一个线程池
	private static ThreadLocal<Connection> tl=new ThreadLocal<>();
	
	/**
	 * 从线程中获取连接
	 * @return
	 * @throws SQLException
	 */
	public static Connection getConnection() {
		//从线程中获取connection
		Connection conn = tl.get();
		if(conn==null){
			try {
				conn=ds.getConnection();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//和当前线程绑�?
			tl.set(conn);
		}
		return conn;
	}
	//...
再修改Dao层获取连接的方式

在这里插入图片描述
在测试发现事务成功!

⑥ 在order_info.jsp上展示数据

在这里插入图片描述

⑦ 在生成订单之后清空购物车
	...
	//4、将order绑定到request中,请求转发到/jsp/order_info.jsp
	request.setAttribute("order", order);
	//5、清空购物车
	request.getSession().removeAttribute("cart");
	...
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

robona

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值