【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表

06-02 1883阅读

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表

🧸安清h:个人主页 

   🎥个人专栏:【Spring篇】【计算机网络】【Mybatis篇】

🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表


目录

🚀1.加入购物车-数据创建

🚀2.加入购物车-实体类

🚀3.加入购物车-持久层

✨3.1规划需要执行的SQL语句

✨3.2设计接口和抽象方法

✨3.3 SQL映射

🚀4.加入购物车-业务层

✨4.1规划异常

✨4.2接口和抽象方法的设计

✨4.3实现接口 

🚀5.加入购物车-控制层

✨5.2设计请求

✨5.3处理请求

🚀6.加入购物车-前端页面

🎯1.显示购物车列表- 持久层

✨1.1规划SQL语句

✨1.2构建VO类

✨1.3设计接口和抽象方法

✨1.4配置SQL映射

🎯2.显示购物车列表- 业务层

🎯3.显示购物车列表- 控制层

✨3.1设计请求

✨3.2处理请求 

🎯4.显示购物车列表- 前端页面

🎃1. 增加购物车商品数量-持久层

✨1.1规划需要执行的SQL语句

✨1.2设计接口和抽象方法

✨1.3配置SQL映射 

🎃 2.增加购物车商品数量-业务层

✨2.1规划异常

✨2.2设计接口和抽象方法

✨ 2.3实现方法

🎃 3.增加购物车商品数量-控制层

✨3.1处理异常

✨3.2设计请求

✨3.3处理请求 

🎃 4.增加购物车商品数量-前端页面


🚀1.加入购物车-数据创建

CREATE TABLE t_cart (
	cid INT AUTO_INCREMENT COMMENT '购物车数据id',
	uid INT NOT NULL COMMENT '用户id',
	pid INT NOT NULL COMMENT '商品id',
	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 (cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

num:当用户重复添加商品时,只修改num就可以了,无需再重复添加商品。 

🚀2.加入购物车-实体类

public class Cart extends BaseEntity{
    private Integer cid;
    private Integer uid;
    private Integer pid;
    private Long price;
    private Integer num;
。。。。。。
}

🚀3.加入购物车-持久层

✨3.1规划需要执行的SQL语句

1.向购物车表中插入数据。

insert into t_cart values(值列表)

2.当当前的商品已经在购物车中存在,则直接更新num的数量即可。

update t_cart set num=? where cid=?

 3.在插入或更新具体执行那个语句,取决于数据库中是否有当前的这个购物车商品的数据,得去查询才能查询。对当前的用户的pid进行查询,加上uid=?,而不是对当前的整张表进行查询。

select * from t_cart where pid=? and uid=?

✨3.2设计接口和抽象方法

创建一个CartMapper接口持久层的文件。

/**
     * 插入购物车数据
     * @param cart 购物车数据
     * @return 受影响的行数
     * 插入时最好放在一个对象中传递,所以用Cart参数列表
     * 插入后在业务层可能调用,需要有返回值判断能否插入成功
     */
    Integer insert(Cart cart);
    /**
     * 更新购物车某件商品的数量
     * @param cid 购物数据id
     * @param num 更新的数量
     * @param modifiedUser 修改人
     * @param modifiedTime 修改时间
     * @return 受影响的行数
     * 更新时涉及到修改人和修改时间,除了cid外,还需要知道数量num
     */
    Integer updateNumByCid(Integer cid, Integer num, String modifiedUser, Date modifiedTime);
    /**
     * 根据用户的id和商品的id来查询购物车中的数据
     * @param uid 用户id
     * @param pid 商品id
     */
    Cart findByUidAndPid(Integer uid,Integer pid);

✨3.3 SQL映射

1.创建一个CartMapper.xml映射文件,添加以上三个抽象方法的SQL映射。



    
        
        
        
        
        
    
    
        insert into t_cart (uid, pid, price, num, created_user, created_time, modified_user, modified_time)
        values (#{uid}, #{pid}, #{price}, #{num}, #{createdUser}, #{createdTime}, #{modifiedUser}, #{modifiedTime})
    
    
        update t_cart set num=#{num},modified_user=#{modifiedUser},modified_time=#{modifiedTime}
        where cid=#{cid}
    
    
    
        select * from t_cart where pid=#{pid} and uid=#{uid}
    

2.进行测试 

@SpringBootTest
public class CartMapperTests {
    @Autowired
    private CartMapper cartMapper;
    @Test
    public void insert(){
        Cart cart = new Cart();
        cart.setNum(3);
        cart.setPid(10000002);
        cart.setUid(6);
        cartMapper.insert(cart);
    }
    @Test
    public void updateNumByCid(){
        cartMapper.updateNumByCid(1,6,"小明",new Date());
    }
    @Test
    public void findByUidAndPid(){
        Cart cart = cartMapper.findByUidAndPid(6,10000002);
        System.err.println(cart);
    }
}

🚀4.加入购物车-业务层

✨4.1规划异常

1.插入数据时可能产生异常:InsertException。

2.更新数据时可能产生异常:UpdateException。

✨4.2接口和抽象方法的设计

分析:

1.首先要进行商品的查询,这里面通过findByUidAndPid方法必须要传递过来的是uid和pid的字段。

2.假设拿到后,就要对原有的数据进行更新,需要传递的字段有:cid,num,username。

    /**
     * 将商品添加到购物车中
     * @param uid 用户id
     * @param pid 商品id
     * @param amount 新增数量
     * @param username 用户名(修改者)
     */
    void addToCart(Integer uid,Integer pid,Integer amount,String username);

✨4.3实现接口 

1.创建一个CartServiceImpl的实现类。

@Service
public class CartServiceImpl implements ICartService {
//购物车的业务层依赖于购物车的持久层和商品的持久层
    @Autowired
    private CartMapper cartMapper;
    @Autowired
    //购物车中的一些定义的字段实际上是从商品表中分离出来的
    private ProductMapper productMapper;
    @Override
    public void addToCart(Integer uid, Integer pid, Integer amount, String username) {
        //查询当前要添加的购物车是否在表中已存在
        Cart result = cartMapper.findByUidAndPid(uid,pid);
        Date date = new Date();
        if(result == null){  //表示这个商品从来没有被添加到购物车中,则进行新增操作
            //创建一个Cart对象
            Cart cart = new Cart();
            //补全数据:首先补全参数传递过来的数据
            cart.setPid(pid);
            cart.setUid(uid);
            //这里的amount暂且理解为在前端加好,把总数传递过来
            cart.setNum(amount);
            //补全价格:来自于商品中的数据
            Product product = productMapper.findById(pid);
            cart.setPrice(product.getPrice());
            //补全四日志
            cart.setCreatedUser(username);
            cart.setCreatedTime(date);
            cart.setModifiedUser(username);
            cart.setModifiedTime(date);
            //执行数据的插入操作
            Integer rows = cartMapper.insert(cart);
            
            if(rows != 1){
                throw new InsertException("插入数据时产生未知的异常");
            }
        }else{  //表示当前商品已经存在于购物车中,则更新这条数据的num值
            Integer num = result.getNum()+amount;
            Integer cid = result.getCid();
            Integer rows = cartMapper.updateNumByCid(cid,num,username,date);
            if(rows != 1){
                throw new UpdateException("更新时产生未知的异常");
            }
        }
    }
}

2. 再创建对应的测试类CartServiceTests。

@SpringBootTest
public class CartServiceTests {
    @Autowired
    private ICartService cartService;
    @Test
    public void addToCart(){
        cartService.addToCart(6,10000013,2,"北伐不成功不改名");
    }
}

🚀5.加入购物车-控制层

1.没有需要处理的异常。

✨5.2设计请求

请求路径:/carts/add_to_cart

请求方式:POST

请求数据:Integer pid,Integer amount,HttpSession session

响应结果:JsonResult

✨5.3处理请求

1.创建一个CartController类,具体代码如下:

@RequestMapping("carts")
@RestController
public class CartController extends BaseController{
    @Autowired
    private ICartService cartService;
    @RequestMapping("add_to_cart")
    public JsonResult addToCart(Integer pid, Integer amount, HttpSession session){
        cartService.addToCart(getuidFromSession(session),pid,amount,getUsernameFromSession(session));
        return new JsonResult(OK);
    }
}

 2.登录后访问:http://localhost:8080/carts/add_to_cart?pid=10000003&amount=1

🚀6.加入购物车-前端页面

在product.html页面给【加入购物车】按钮添加点击事件,并发送ajax请求。

$("#btn-add-to-cart").click(function (){
				$.ajax({
					url:"/carts/add_to_cart",
					type:"POST",
					data:{
						"pid":id,
						"amount":$("#num").val()
					},
					dataType:"JSON",
					success:function (json){
						if(json.state==200){
							alert("加入购物车成功");
						}else{
							alert("加入购物车失败");
						}
					},
					error:function (xhr){
						alert("加入购物车时产生未知的异常"+xhr.message);
					}
				});
			});

在ajax函数中data参数的数据设置的方式:

  • data:$("form表单选择").serialize()。适合要么就是可以全部选择的,或者手动输入的串的类型。当参数过多并且在同一个字符串中。
  • data:new FormData($("form表单选择")[0])。只适用提交文件,其他形式提交不了。
  • data:"username=Tom"。适合参数值固定并且参数值列表有限,可以进行手动拼接。
    let user = "tom";
    data:"username="+user
  • 适用JSON格式提交数据:
    data:{
        "username":"tom",
        "age":18,
        "sex":0
    }

    🎯1.显示购物车列表- 持久层

    ✨1.1规划SQL语句

    【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表

    分析上图可知,红线框住的图片和商品标题来自于product表,而蓝线框住的应该属于 cart表,单价和数量应该是从购物车中传过来的,再根据两者计算总金额。由于数据来自于两张表中的部分字段,所以要用到关联查询。

    #多表查询如果字段不重复则不需要显式声明字段属于哪张表
    select cid,
           uid,
           pid,
           t_cart.price,
           t_cart.num,
           t_product.image,
           t_product.title,
           t_product.price as real
    from t_cart left join t_product on t_cart.pid=t_product.id
    where uid=#{uid}
    order by t_cart.createdTime DESC;

    ✨1.2构建VO类

     VO:Value Object,值对象。当进行select查询时,查询的结果属于多张表中的内容,此时发现结果集不能直接使用某个POJO实体类来接收,POJO实体类不能包含多表查询出来的结果。解决方案:重新构建一个新的对象,这个对象用于存储所查询出来的结果集对应的映射,所以把这样的对象称之为值对象。

    在com.cy.store下新建一个包VO,在VO包里创建CartVO类。 

    //购物车数据的VO类(Value Object)值对象
    public class CartVO implements Serializable {
        private Integer cid;
        private Integer uid;
        private Integer pid;
        private Long price;
        private Integer num;
        private String title;
        private String image;
        private Long realPrice;
    ......
    }

    ✨1.3设计接口和抽象方法

    在CartMapper中编写如下代码:

    List findVOByUid(Integer uid);

    ✨1.4配置SQL映射

        
            select cid,
                   uid,
                   pid,
                   t_cart.price,
                   t_cart.num,
                   t_product.image,
                   t_product.title,
                   t_product.price as realPrice
            from t_cart left join t_product on t_cart.pid=t_product.id
            where uid=#{uid}
            order by t_cart.createdTime DESC
        

    单元测试

        @Test
        public void findVOByUid(){
            System.out.println(cartMapper.findVOByUid(6));
        }

    🎯2.显示购物车列表- 业务层

    1.先编写业务层的接口方法。

    List getVOByUid(Integer uid);

    2.在实现类中实现方法。

    @Override
        public List getVOByUid(Integer uid) {
            List list = cartMapper.findVOByUid(uid);
            return list;
        }

    🎯3.显示购物车列表- 控制层

    ✨3.1设计请求

    请求路径:/carts/(只要发一个carts就可以把列表返回,不需要carts下的什么)

    请求方式:GET

    请求数据:HttpSession session

    响应结果:JsonResult

    ✨3.2处理请求 

    1.实现请求处理方法的代码编写。

        @RequestMapping({"/",""})
        public JsonResult getVOByUid(HttpSession session){
            List data = cartService.getVOByUid(getuidFromSession(session));
            return new JsonResult(OK,data);
        } 

    2.先登录再进行功能测试,访问http://localhost:8080/carts。

    🎯4.显示购物车列表- 前端页面

    要把cart.html页面通过向Controller层中的getVOByUid方法发送请求就可以返回所有的数据。

    1.先注释掉以下代码:

     
    

    2.用户一打开页面就自动发送请求,请求数据。读取form表单,对它的结构做一个了解,因为要把数据显示在form表单中。

    • action="orderConfirm.html"
    • tbody标签的id="cart-list"属性,自动加载的内容需要体现在tbody中。
    • type="button":结算按钮的submit改成button,后续需要传数据。

      3.ready()函数来完成自动的ajax请求的提交和处理。

      				$(document).ready(function () {
      				showCartList();
      			})
      			;
      				//展示购物车列表数据
      				function showCartList() {
      				$("#cart-list").empty();
      				$.ajax({
      				url: "/carts",
      				type: "GET",
      				dataType: "JSON",
      				success: function(json) {
      				let list = json.data;
      				for (var i = 0; i \n' +
      				'\n' + 
      				//在这里给复选框一个cid值,在往后点击结算的时候会把这个cid值传递给下个页面
      				//把这个数据提交给另一个页面是以参数的形式提交,所以这个表单一定要有内部属性
      				'\n' +
      				'\n' +
      				'【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表\n' +
      				'#{title}#{msg}\n' +
      				'¥#{singlePrice}\n' +
      				'\n' +
      				'\n' +
      				'\n' +
      				'\n' +
      				'\n' +
      				'#{totalPrice}\n' +
      				'\n' +
      				'\n' +
      				'\n' +
      				'';
      				tr = tr.replaceAll(/#{cid}/g, list[i].cid);
      				tr = tr.replaceAll(/#{image}/g, list[i].image);
      				tr = tr.replaceAll(/#{title}/g, list[i].title);
      				tr = tr.replaceAll(/#{singlePrice}/g, list[i].realPrice);
      				tr = tr.replaceAll(/#{num}/g, list[i].num);
      				tr = tr.replaceAll(/#{totalPrice}/g, list[i].realPrice * list[i].num);
      				if (list[i].realPrice  
      

      🎃1. 增加购物车商品数量-持久层

      ✨1.1规划需要执行的SQL语句

      1.执行更新t_cart表记录的num的值,无需重复开发。

      update t_cart set num=#{num},modified_time={modifiedTime},modified_user=#{modifiedUser} where cid=#{cid}

      2.根据cid查询购物车的这条记录是否存在。

      select * from t_cart where cid=?

      ✨1.2设计接口和抽象方法

      Cart findByCid(Integer cid);

      ✨1.3配置SQL映射 

          
              select * from t_cart where cid=#{cid}
          

      编写单元测试。

          @Test
          public void findByCid(){
              System.out.println(cartMapper.findByCid(2));
          }

      🎃 2.增加购物车商品数量-业务层

      ✨2.1规划异常

      1.在更新时会产生更新异常。

      2.查询到的数据是否有访问权限。

      3.查询的数据不存在,抛出:CartNotFoundException异常。

      public class CartNotFoundException extends ServiceException{
          public CartNotFoundException() {
              super();
          }
          public CartNotFoundException(String message) {
              super(message);
          }
          public CartNotFoundException(String message, Throwable cause) {
              super(message, cause);
          }
          public CartNotFoundException(Throwable cause) {
              super(cause);
          }
          protected CartNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
              super(message, cause, enableSuppression, writableStackTrace);
          }
      }

      ✨2.2设计接口和抽象方法

          /**
           * 更新用户的购物车数据
           * @param cid 
           * @param uid
           * @param username 
           * @return 增加成功后新的数量
           */
          Integer addNum(Integer cid,Integer uid,String username);

      ✨ 2.3实现方法

          @Override
          public Integer addNum(Integer cid, Integer uid, String username) {
              Cart result = cartMapper.findByCid(cid);
              if(result == null){
                  throw new CartNotFoundException("数据不存在");
              }
              if(!result.getUid().equals(uid)){
                  throw new AccessDeniedException("数据非法访问");
              }
              Integer num = result.getNum()+1;
              Integer rows = cartMapper.updateNumByCid(cid,num,username,new Date());
              if(rows != 1){
                  throw new UpdateException("更新时产生异常");
              }
              //返回新的购物车总量
              return num;
          }

      🎃 3.增加购物车商品数量-控制层

      ✨3.1处理异常

      else if(e instanceof CartNotFoundException) {
                  result.setState(4007);
                  result.setMessage("购物车数据不存在的异常");
              }

      ✨3.2设计请求

      请求路径:/carts/{cid}/num/add

      请求方式:POST

      请求数据:Integer cid,HttpSession session

      响应结果:JsonResult

      ✨3.3处理请求 

          @RequestMapping("{cid}/num/add")
          public JsonResult addNum(Integer cid,HttpSession session){
              Integer data = cartService.addNum(cid,getuidFromSession(session),getUsernameFromSession(session));
              return new JsonResult(OK,data);
          }

      先登录在访问url地址对应的地址。 

      🎃 4.增加购物车商品数量-前端页面

      1.前面已经在onclick中改过里面的内容,所以无需重复修改了,但是需要重新编写addNum()以确保点击后能够增加数量。

       
      
      			function addNum(cid){
      				$.ajax({
      					url: "/carts/"+cid+"/num/add",
      					type: "POST",
      					dataType: "JSON",
      					success: function (json) {
      						if (json.state == 200) {
      							//先拿到数量展示的id,
      							$("#goodsCount"+cid).val(json.data)
      							//由于price的值不是放在val控件上,也不是放在某一个属性上,通过html来拿,
      							//html就是拿到它标签内部的这个东西,如果内部是个串拿到的就是个串
      							//获取某个标签内部的内容:文本、标签
      							//因为刚好这个内容即:singlePrice作为一个子内容放在了开始和结束的中间
      							let price = $("#goodsPrice"+cid).html();
      							let totalPrice = price * json.data;
      							$("#goodsCast"+cid).html(totalPrice);
      						} else {
      							alert("增加购物车商品数量失败")
      						}
      					},
      					error: function (xhr) {
      						alert("增加购物车商品数量时产生未知的异常!"+xhr.message);
      					}
      				});
      				}
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码