本文的核心内容:数据库表设计之购物车,利用Session暂时存储购物车信息。
数据库库表设计对于一个软件系统的设计相当重要,这部分知识需要长时间和项目的积累。因为,我的梦想不止CURD!!!Maps在博客写下积累,以供学习和参考。
在电商软件,必不可少的模块就是购物车
我提供、分享两种设计方法:
一:维护一张购物车表,以用户ID为外键
一个用户一个购物车,用户注册成功的同时,为用户在购物车表内维护一个专属于用户的购物车。(根据我以前学到的知识,这一步可以为用户表创建Insert触发法器,当用户注册成功[触发器将用户ID作为外键插入购物车表],用户即拥有了唯一的购物车)
T_Car
字段 |
类型 |
说明
扫描二维码关注公众号,回复:
1426608 查看本文章
|
Car_ID |
Varchar2(36) |
购物车编号 主键 |
User_ID |
Varchar2(36) |
外键 用户唯一标识 |
Car_Status |
Varchar2(4) |
购物车状态 |
T_Shop_Item
字段 |
类型 |
说明 |
Shop_item_ID |
Varchar2(36) |
购物项编号 主键 |
Car_ID |
Varchar2(36) |
购物车编号 外键 |
Product_ID |
Varchar2(36) |
商品编号 外键 |
Count |
Number(4) |
数量 |
Price |
number(8,2) |
价格 |
ProductName |
Varchar(30) |
商品名 |
这么实现购物车的弊端:①:非该网站的注册用户无法将商品加入购物车。这与现实的情况不符合。一般我们访问某宝,某东,我们可以以游客的方式将商品加入购物车,直到下订单、付款时才要求我们必须登录。②:每个用户维护一下购物车似乎不太明智,顾客将商品加入购物车到下订单,完成交易,这一需求对数据库更改频繁。
二:所有用户共用一个”购物车”
我们可以直接以用户ID为标识,区分购物车商品所属的用户。
T_Shop_Item
字段 |
类型 |
说明 |
Shop_item_ID |
Varchar2(36) |
购物项编号 主键 |
User_ID |
Varchar2(36) |
用户编号 外键 |
ProductID |
Varchar2(36) |
商品编号 外键 |
Count |
Number(4) |
数量 |
Price |
number(8,2) |
价格 |
ProductName |
Varchar(30) |
商品名 |
即使减少了一张购物车表,但是这表还需要用户登录才能记录用户添加商品情况。
三:利用Session暂时存储购物车内的东西
[用户不登录就能添加商品到购物车;用户登录状态将Session中的信息存入非关系型数据库、关系型数据库。将购物车内的东西持久化存储]
明确一点:Session -> 一次会话有效(在用户不关闭浏览器的前提下,默认存在30分钟;用户关闭浏览器再次打开后,未登录用户的购物车将清空。)
解决如何用Session存储购物车内信息。
第一个难点:那么如何准确区分不同的商品? (自然是商品ID)
第二个难点:那么如何准确标记一个进入购物车的商品? (只有商品ID是不行的)
商品ID,通过商品ID,我们可以查询到商品详情。(价格、名称等等)
同一商品的购买数量。这一信息是不存在于商品详情的。【重点,不能忽略】
这两个信息必须存储。于是我想到Map(两个原因)。
①:存储两个值
Map<String,Integer> map=new HashMap<String,Integer>();
key存储 商品ID, value存储 商品数量(购买数量)
②:保证商品ID(键)的唯一性
Map的特点:键唯一,值可以重复。我们以商品ID为键,这样就可以保证商品的唯一性。
我们再将map存入Session中就可以了。
当用户添加商品时,只需先从Session中取出map,迭代遍历判断key是否已经存在,若存在取value值加1;若不存在则将商品ID作为key,value数量默认为1,Put进map。
当用户(未登录)查看购物车时,只需从Session中取商品ID和数量,就可以显示购车内商品的详细信息,计算购物车内的商品总价格。
这种存储方式简化了添加商品进入购物车和删除购物车里商品的操作。但是却不得不再次封装一个Map对象将购物车详情页面的信息存储进去,以供购物车展示页面显示数据。
(这是我第一次考虑的存储方案,写到查看购物车详情页面才发现不合理之处。)
改进版本:
Map <String,Goods> map=new HashMap<String,Goods> ();
Key ->商品id
Value->购物车页面需要展示的商品详情(商品名、商品ID、商品数量、商品价格等)
核心:value值维护不再是一个商品数量,而是我们封装的模拟购物车实体对象
JSP页面的效果图
源代码:添加商品的Action
//添加商品Action public String addToCar() throws Exception{ //尝试从Session取出购物车 ValueStack vs=ActionContext.getContext().getValueStack(); Map<String,Goods> car=(Map<String,Goods>)vs.findValue("#session.car"); BookService service=new BookServiceImpl(); if(car==null){ //判断购物车是否存在 //不存在则创建,将用户添加的商品加入Map 存入Session Map<String,Goods> map=new HashMap<String,Goods>(); //查询数据将商品详情查询出出来,把我们感兴趣的属性封装到Goods实体中 Book book=service.getSingleBook(bookid); Goods goods=new Goods(); goods.setBookid(book.getBookid()); goods.setCount(1); goods.setPrice(book.getPrice()); goods.setCurrentprice(book.getCurrentprice()); goods.setProductname(book.getProductname()); map.put(bookid, goods); vs.setValue("#session.car", map); }else{ //判断用户添加的商品是否已经存在于购物车里 //若存在根据key取出Goods->修改商品选购的数量 //不存在则是首次添加,数量默认为1 ,将商品Put入map if(car.containsKey(bookid)){ Goods product=car.get(bookid); product.setCount(product.getCount()+1); }else{ Book book=service.getSingleBook(bookid); Goods goods=new Goods(); goods.setBookid(book.getBookid()); goods.setCount(1); goods.setPrice(book.getPrice()); goods.setCurrentprice(book.getCurrentprice()); goods.setProductname(book.getProductname()); car.put(bookid, goods); } } return Action.SUCCESS; }