【基于SprintBoot+Mybatis+Mysql】电脑商城项目之显示勾选的购物车数据和创建订单
🧸安清h:个人主页
🎥个人专栏:【Spring篇】【计算机网络】【Mybatis篇】
🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。
目录
🚀1.显示勾选的购物车数据-持久层
✨1.1规划SQL语句
✨1.2设计接口和抽象方法
✨1.3配置SQL映射
🚀2.显示勾选的购物车数据-业务层
✨2.2设计接口和抽象方法
✨2.3完成抽象方法的设计
🚀3.显示勾选的购物车数据-控制层
✨3.1设计请求
✨3.2处理请求
🚀4.1显示勾选的购物车数据-前端页面
🚀4.2购物车页面显示收货地址列表-前端页面
🎯1.创建订单-数据表
🎯2.创建订单-实体类
🎯3.创建订单-持久层
✨3.1规划SQL语句
✨3.2设计接口和抽象方法
✨3.3配置SQL映射
🎯4.创建订单-业务层
🎯5.创建订单-控制层
✨5.1设计请求
✨5.2处理请求
🎯6.创建订单-前端页面
🚀1.显示勾选的购物车数据-持久层
✨1.1规划SQL语句
1.用户在购物车列表中通过随即勾选相关的商品,在点击“结算”按钮后跳转到结算页面,在这个页面中需要展示用户在上个页面所勾选的购物车对应的数据。列表的展示,展示的内容还是来自于购物车表。两个页面需要将用户勾选的cid传递给下一个页面。
当前只要cid的值能够达到in里面的任意一个值,都属于满足整体的where条件。用户在前端所传递过来的这个?的值,在后台可以用一个集合来接收到,然后层层传递给mapper,mapper用一个集合来代替就行了,只要cid属于集合中任意一个数就符合条件了。
selectcid,uid,pid,t_cart.price,t_cart.num,title,t_product.price as realPrice,image
from t_cart
left join t_product on t_cart.pid = t_product.id
where cid in (?,?,?)
order by t_cart.created_time desc
✨1.2设计接口和抽象方法
List<CartVO> findVOByCid(Integer[] cids);
✨1.3配置SQL映射
<select id="findVOByCid" resultType="com.cy.store.Vo.CartVO">selectcid,uid,pid,t_cart.price,t_cart.num,title,t_product.price as realPrice,imagefrom t_cartleft join t_product on t_cart.pid = t_product.idwhere cid in (<foreach collection="array" item="cid" separator=","> --把每个cid拿到,中间用,分隔#{cid}</foreach>)order by t_cart.created_time desc</select>
进行单元测试
@Testpublic void findVOByCids() {Integer[] cids = {1,2,3,9};System.out.println(cartMapper.findVOByCid(cids));}
🚀2.显示勾选的购物车数据-业务层
2.1查询语句,无异常规划。
✨2.2设计接口和抽象方法
List<CartVO> getVOByCid(Integer uid, Integer[] cids);
✨2.3完成抽象方法的设计
@Overridepublic List<CartVO> getVOByCid(Integer uid,Integer[] cids) {List<CartVO> list = cartMapper.findVOByCid(cids);Iterator<CartVO> it = list.iterator();while (it.hasNext()) {CartVO cartVO = it.next();if (!cartVO.getUid().equals(uid)) { //表示当前的数据不属于当前的用户//从集合中移除这个元素list.remove(cartVO);}}return list;}
🚀3.显示勾选的购物车数据-控制层
✨3.1设计请求
请求路径:/carts/list
请求方式:POST
请求数据:Integer[] cids ,HttpSession session
响应结果:JsonResult<List<CartVO>>
✨3.2处理请求
@RequestMapping("list")public JsonResult<List<CartVO>> getVOByCid(Integer[] cids, HttpSession session) {List<CartVO> data = cartService.getVOByCid(getuidFromSession(session), cids);return new JsonResult<>(OK, data);}
🚀4.1显示勾选的购物车数据-前端页面
1.把type属性改成submit,让其自动提交。
<input type="submit" value=" 结 算 " class="btn btn-primary btn-lg link-account" />
2.orderConfirm.html页面中添加自动加载从上个页面中传递过来的cids数据,再去请求ajax,再在ajax中进行填充到当前的某个区域。
3.注释掉以下代码:
<script src="../js/orderConfirm.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">$(document).ready(function() {showCartList();});function showCartList() {$("#cart-list").empty();$.ajax({url: "/carts/list",type: "GET",data: location.search.substr(1), //截问号后的第一个参数dataType: "JSON",success: function(json) {if (json.state == 200) {let list = json.data;let allCount = 0;let allPrice = 0;for (let i = 0; i < list.length; i++) {let tr = '<tr>\n' +'<td><img src="..#{image}collect.png" class="img-responsive" /></td>\n' +'<td>#{title}</td>\n' +'<td>¥<span>#{price}</span></td>\n' +'<td>#{num}</td>\n' +'<td><span>#{totalPrice}</span></td>\n' +'</tr>';tr = tr.replace("#{image}",list[i].image);tr = tr.replace("#{title}",list[i].title);tr = tr.replace("#{price}",list[i].realPrice);tr = tr.replace("#{num}",list[i].num);tr = tr.replace("#{totalPrice}",list[i].realPrice*list[i].num);$("#cart-list").append(tr);allCount += list[i].num;allPrice += list[i].realPrice*list[i].num;}$("#all-count").html(allCount);$("#all-price").html(allPrice);}},error: function (xhr) {alert("结算时发生未知的异常"+xhr.status);}});}
</script>
🚀4.2购物车页面显示收货地址列表-前端页面
1.收货地址存放在一个select下拉列表中,将查询到的当前登录用户的收货地址动态的加载到这个下拉列表中.从数据库的角度是一个select查询语句。已经编写了根据用户的uid来查询当前用户的收货地址数据。
2.orderConfirm.html页面中,收货地址数据的展示需要自动进行加载,需要将方法的逻辑放在ready函数中。
$(document).ready(function() {showCartList();showAddressList();});
function showCartList() {$("#address-list").empty();$.ajax({url: "/addresses/",type: "GET",dataType: "JSON",success: function(json) {if (json.state == 200) {let list = json.data;for (let i = 0; i < list.length; i++) {var opt = '<option value="#{aid}">#{name} #{tag} #{provinceName}#{cityName}#{areaName}#{address} #{tel}</option>';opt = opt.replace("#{aid}",list[i].aid);opt = opt.replace("#{name}",list[i].name);opt = opt.replace("#{tag}",list[i].tag);opt = opt.replace("#{provinceName}",list[i].provinceName);opt = opt.replace("#{cityName}",list[i].cityName);opt = opt.replace("#{areaName}",list[i].areaName);opt = opt.replace("#{address}",list[i].address);opt = opt.replace("#{tel}",list[i].tel);$("#address-list").append(opt);}}},error: function (xhr) {alert("结算时发生未知的异常"+xhr.status);}});}
🎯1.创建订单-数据表
在数据库store中创建数据表t_order和t_order_item。
CREATE TABLE t_order (oid INT AUTO_INCREMENT COMMENT '订单id',uid INT NOT NULL COMMENT '用户id',recv_name VARCHAR(20) NOT NULL COMMENT '收货人姓名',recv_phone VARCHAR(20) COMMENT '收货人电话',recv_province VARCHAR(15) COMMENT '收货人所在省',recv_city VARCHAR(15) COMMENT '收货人所在市',recv_area VARCHAR(15) COMMENT '收货人所在区',recv_address VARCHAR(50) COMMENT '收货详细地址',total_price BIGINT COMMENT '总价',status INT COMMENT '状态:0-未支付,1-已支付,2-已取消,3-已关闭,4-已完成',order_time DATETIME COMMENT '下单时间',pay_time DATETIME COMMENT '支付时间',created_user VARCHAR(20) COMMENT '创建人',created_time DATETIME COMMENT '创建时间',modified_user VARCHAR(20) COMMENT '修改人',modified_time DATETIME COMMENT '修改时间',PRIMARY KEY (oid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE t_order_item (id INT AUTO_INCREMENT COMMENT '订单中的商品记录的id',oid INT NOT NULL COMMENT '所归属的订单的id',pid INT NOT NULL COMMENT '商品的id',title VARCHAR(100) NOT NULL COMMENT '商品标题',image VARCHAR(500) COMMENT '商品图片',price BIGINT COMMENT '商品价格',num INT COMMENT '购买数量',created_user VARCHAR(20) COMMENT '创建人',created_time DATETIME COMMENT '创建时间',modified_user VARCHAR(20) COMMENT '修改人',modified_time DATETIME COMMENT '修改时间',PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
🎯2.创建订单-实体类
在com.cy.store.entity包下创建Order类并使其继承基类。
public class Order extends BaseEntity {private Integer oid;private Integer uid;private String recvName;private String recvPhone;private String recvProvince;private String recvCity;private String recvArea;private String recvAddress;private Long totalPrice;private Integer status;private Date orderTime;private Date payTime;
。。。。。。
}
在com.cy.store.entity包下创建OrderItem类并使其继承基类。
public class OrderItem extends BaseEntity {private Integer id;private Integer oid;private Integer pid;private String title;private String image;private Long price;private Integer num;
......
}
🎯3.创建订单-持久层
✨3.1规划SQL语句
1.将数据插入到订单表中。
insert into t_order (oid除外所有的字段) values (字段值)
2.将数据插入订单项表中。
insert into t_order_item (id除外所有的字段) values (字段值)
✨3.2设计接口和抽象方法
创建一个OrderMapper接口,接口中添加以上两个SQL对象的抽象方法。
public interface OrderMapper {/*** 插入订单数据* @param order 订单数据* @return 受影响的行数*/Integer insertOrder(Order order);/*** 插入订单项的数据* @param orderItem 订单项数据* @return 受影响的行数*/Integer insertOrderItem(OrderItem orderItem);
}
✨3.3配置SQL映射
1.创建OrderMapper.xml文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.store.mapper.OrderMapper"><insert id="insertOrder" useGeneratedKeys="true" keyProperty="oid">insert into t_order (uid, recv_name, recv_phone, recv_province, recv_city, recv_area, recv_address,total_price,status, order_time, pay_time, created_user, created_time, modified_user,modified_time) values (#{uid}, #{recvName}, #{recvPhone}, #{recvProvince}, #{recvCity}, #{recvArea},#{recvAddress}, #{totalPrice}, #{status}, #{orderTime}, #{payTime}, #{createdUser},#{createdTime}, #{modifiedUser}, #{modifiedTime})</insert><insert id="insertOrderItem" useGeneratedKeys="true" keyProperty="id">insert into t_order_item (oid, pid, title, image, price, num, created_user,created_time, modified_user, modified_time) values (#{oid}, #{pid}, #{title}, #{image}, #{price}, #{num}, #{createdUser},#{createdTime}, #{modifiedUser}, #{modifiedTime})</insert>
</mapper>
2.单元测试。
@Testpublic void insertOrder(){Order order = new Order();order.setUid(6);order.setRecvName("子敬");order.setRecvPhone("384570219");orderMapper.insertOrder(order);}@Testpublic void insertOrderItem(){OrderItem orderItem = new OrderItem();orderItem.setOid(1);orderItem.setPid(10000002);orderItem.setTitle("广博(GuangBo)皮面日程本子 计划记事本效率手册米色FB60322");orderMapper.insertOrderItem(orderItem);}
🎯4.创建订单-业务层
1.在IAddressService接口中定义根据收货地址的id获取收货地址的数据。
Address getByAid(Integer aid);
2.实现方法。
@Overridepublic Address getByAid(Integer aid,Integer uid) {Address address =addressMapper.findByAid(aid);if(address == null){throw new AddressNotFoundException("收货地址数据不存在");}if(address.getUid().equals(uid)){throw new AccessDeniedException("非法数据访问");}address.setProvinceCode(null);address.setCityCode(null);address.setAreaCode(null);address.setCreatedUser(null);address.setCreatedTime(null);address.setModifiedUser(null);address.setModifiedTime(null);return address;}
3.在service包下创建IOrderService接口添加抽象方法用于创建订单。
public interface IOrderService {Address create(Integer aid,Integer uid,String username,Integer[] cids);
}
4.创建实现类OrderServiceImpl。
@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate IAddressService addressService;@Autowiredprivate ICartService cartService;@Overridepublic Order create(Integer aid, Integer uid, String username, Integer[] cids) {//即将要下单的列表List<CartVO> list = cartService.getVOByCid(uid,cids);//计算商品的总价Long totaolPrice = 0L;Address address = addressService.getByAid(aid, uid);Order order = new Order();order.setUid(uid);//收货地址数据order.setRecvName(address.getName());order.setRecvPhone(address.getPhone());order.setRecvProvince(address.getProvinceName());order.setRecvCity(address.getCityName());order.setRecvArea(address.getAreaName());order.setRecvAddress(address.getAddress());//支付,总价,时间order.setStatus(0);order.setTotalPrice(totaolPrice);order.setOrderTime(new Date());//日志order.setCreatedUser(username);order.setCreatedTime(new Date());order.setModifiedUser(username);order.setModifiedTime(new Date());Integer rows = orderMapper.insertOrder(order);if(rows != 1){throw new InsertException("插入时异常");}//创建订单详细项的数据for(CartVO c : list){//创建一个订单项数据对象OrderItem orderItem = new OrderItem();orderItem.setOid(order.getOid());orderItem.setPid(c.getPid());orderItem.setTitle(c.getTitle());orderItem.setImage(c.getImage());orderItem.setPrice(c.getPrice());orderItem.setNum(c.getNum());//日志字段orderItem.setCreatedUser(username);orderItem.setCreatedTime(new Date());orderItem.setModifiedUser(username);orderItem.setModifiedTime(new Date());//插入数据操作rows = orderMapper.insertOrderItem(orderItem);if(rows != 1){throw new InsertException("插入时异常");}orderMapper.insertOrderItem(orderItem);}return order;}
5.创建测试方法并完成测试。
@SpringBootTest
public class OrderServiceTests {@Autowiredprivate IOrderService orderService;@Testpublic void create(){Integer[] cids = {3,4};Order order = orderService.create(12,6,"小明",cids);System.out.println(order);}}
🎯5.创建订单-控制层
✨5.1设计请求
请求路径:/orders/create/
请求参数:Integer aid,Integer[] cids,HttpSession session
请求类型:POST
响应结果:JsonResult<Order>
✨5.2处理请求
创建一个OrderController类,并编写处理请求方法。
@RequestMapping("/orders/")
@RestController
public class OrderController extends BaseController{@Autowiredprivate IOrderService orderService;@RequestMapping("create")public JsonResult<Order> create(Integer aid, Integer[] cids, HttpSession session){Order data = orderService.create(aid,getuidFromSession(session),getUsernameFromSession(session),cids);return new JsonResult<>(OK,data);}
}
🎯6.创建订单-前端页面
在订单确定页面中添加发送请求的处理方法。
$("#btn-create-order").click(function() {let aid = $("#address-list").val();let cids = location.search.substr(1);$.ajax({url: "/orders/create",type: "GET",data: "aid="+aid + "&" + cids,dataType: "JSON",success: function(json) {if (json.state == 200) {location.href = "payment.html";alert("订单创建成功");console.log(json.data) //调试} else {alert("创建订单失败" + json.message);}},error: function(xhr) {alert("创建订单数据时产生未知的异常" + xhr.status);}});});
感谢各位的陪伴,最后一篇也更完啦🎉🎉🎉