赞
踩
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;
public class Cart extends BaseEntity{
private Integer cid;
private Integer uid;
private Integer pid ;
private Long price;
private Integer num;
//...
insert into t_cart () values ()
update t_cart set num = ? where cid=?
select * from t_cart where cid = ? and uid = ?
public interface CartMapper {
//插入购物车数据
Integer insert(Cart cart);
//更新购物车某件商品的数量
Integer updateNumByCid(Integer cid, Integer num,
String modifiedUser, Date modifiedTime);
//根据用户的id和商品的id来查询购物车的数据
Cart findByUidAndPid(Integer uid, Integer pid);
}
<?xml version="1.0" encoding="UTF8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cy.store.mapper.CartMapper"> <resultMap type="com.cy.store.entity.Cart" id="CartEntityMap"> <id property="cid" column="cid"/> <result property="createdUser" column="created_user"/> <result property="createdTime" column="created_time"/> <result property="modifiedUser" column="modified_user"/> <result property="modifiedTime" column="modified_time"/> </resultMap> <insert id="insert" useGeneratedKeys="true" keyProperty="cid"> 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}) </insert> <update id="updateNumByCid"> update t_cart set num=#{num}, modified_user=#{modifiedUser}, modified_time=#{modifiedTime} where cid=#{cid} </update> <select id="findByUidAndPid" resultMap="CartEntityMap"> select * from t_cart where uid=#{uid} and pid=#{pid} </select> </mapper>
@Autowired private CartMapper cartMapper; @Test public void insert(){ Cart cart = new Cart(); cart.setUid(10); cart.setPid(10000011); cart.setNum(2); cart.setPrice(1000L); cartMapper.insert(cart); } @Test public void updateNumByCid(){ cartMapper.updateNumByCid(1,4,"张三", new Date()); } @Test public void findByUidAndPid() { System.out.println(cartMapper.findByUidAndPid(10, 10000011)); }
public interface ICartService {
/**
* 添加商品到购物车
* @param uid 用户id
* @param pid 商品id
* @param amount 新增数量
* @param username 用户名(修改者)
*/
void addToCart(Integer uid, Integer pid, Integer amount, String username);
}
@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 = new Cart(); cart.setUid(uid); cart.setPid(pid); cart.setNum(amount); //补全价格,来自于商品中的数据 Product product = productMapper.findById(pid); cart.setPrice(product.getPrice()); //补全4项日志 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 rows = cartMapper.updateNumByCid( result.getCid(), num, username, date ); if(rows != 1) { throw new UpdateException("更新数据时产生未知的异常"); } } }
@Autowired
private ICartService cartService;
@Test
public void addToCart() {
cartService.addToCart(10,10000003,5,"管理员");
}
/carts/add_to_cart
get
pid,amount,session
JsonResult<Void>
@RequestMapping("carts")
@RestController
public class CartController extends BaseController{
@Autowired
private ICartService cartService;
@RequestMapping("add_to_cart")
public JsonResult<Void> addToCart(
Integer pid,
Integer amount,
HttpSession session) {
cartService.addToCart(getuidFromSession(session),pid,amount,getUsernameFromSession(session));
return new JsonResult<>(OK);
}
}
在ajax函数中data参数的数据设置的方式:
data: #("form表单选择").serialize()
:用于参数比较多,并且表单的参数都需要提交data: new FormData($("form表单选择")[0])
:用于提交文件data: "username=Tom"
:用于参数值固定并且参数值列表有限data: {
"username": "TOM",
"age": 18,
"sex": 0
}
在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); } }); });
登录后将对应用户的购物车数据展示出来。
规划SQL语句
select
cid,uid,pid,t_cart.price,t_cart.num,
t_product.title,t_product.image,t_product.price as realPrice
from
t_cart left join t_product on t_cart.pid = t_product.id
where
uid = ?
order by
t_cart.created_time desc;
VO:Value Object,值对象。当进行select查询时,查询的结果属于多张表中的内容,此时发现结果集不能直接使用某个pojo实体类来接收,pojo实体类不能包含多表查询出来的结果。解决方式是:重新构建一个新的对象,这个对象用于存储所查询出来的结果集对应的映射,所以把这个对象称之为 值对象。
在store包下创建一个vo包,在vo包下创建CartVO实体类:
/** 购物车数据的VO类 */
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;
//...
设计接口
在CartMapper接口中定义抽象方法
List<CartVO> findVOByUid(Integer uid);
映射SQL
<select id="findVOByUid" resultType="com.cy.store.vo.CartVO">
select
cid, uid, pid, t_cart.price, t_cart.num,
t_product.title, t_product.image, 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.created_time desc;
</select>
测试
@Test
public void findVOByUid() {
System.out.println(cartMapper.findVOByUid(10));
}
List<CartVO> getVOByUid(Integer uid)
@Override
public List<CartVO> getVOByUid(Integer uid) {
return cartMapper.findVOByUid(uid);
}
/carts/
session
get
JsonResult<List<CartVO>>
@RequestMapping({"","/"})
public JsonResult<List<CartVO>> getVOByUid(HttpSession session) {
List<CartVO> data = cartService.getVOByUid(getuidFromSession(session));
return new JsonResult<>(OK, data);
}
1.注释掉cart.js文件
<!-- <script src="../js/cart.js" type="text/javascript" charset="utf-8"></script> -->
2.注意form表单结构。将“结算按钮”改成type="button"
属性值。
3.ready()函数来完成自动的ajax请求的提交和处理。
<script type="text/javascript"> $(document).ready(function () { showCartList(); }); /** 展示购物车列表数据*/ function showCartList() { //清空tbody标签的数据 $("#cart-list").empty(); $.ajax({ url: "/carts", type: "get", dataType: "JSON", success: function (json) { let list = json.data; for (let i = 0; i < list.length; i++) { let tr = '<tr>\n' + '<td>\n' + '<input name="cids" value="#{cid}" type="checkbox" class="ckitem" />\n' + '</td>\n' + '<td><img src="..#{image}collect.png" class="img-responsive" /></td>\n' + '<td>#{title}#{msg}</td>\n' + '<td>¥<span id="goodsPrice#{cid}">#{singlePrice}</span></td>\n' + '<td>\n' + '<input id="price-#{cid}" type="button" value="-" class="num-btn" οnclick="reduceNum(1)" />\n' + '<input id="goodsCount#{cid}" type="text" size="2" readonly="readonly" class="num-text" value="#{num}">\n' + '<input id="price+#{cid}" class="num-btn" type="button" value="+" οnclick="addNum(1)" />\n' + '</td>\n' + '<td><span id="goodsCast#{cid}">#{totalPrice}</span></td>\n' + '<td>\n' + '<input type="button" οnclick="delCartItem(this)" class="cart-del btn btn-default btn-xs" value="删除" />\n' + '</td>\n' + '</tr>' tr = tr.replace(/#{cid}/g, list[i].cid); tr = tr.replace(/#{image}/g, list[i].image); tr = tr.replace(/#{title}/g, list[i].title); tr = tr.replace(/#{msg}/g, list[i].realPrice); tr = tr.replace(/#{num}/g, list[i].num); tr = tr.replace(/#{singlePrice}/g, list[i].price); tr = tr.replace(/#{totalPrice}/g, list[i].price*list[i].num); $("#cart-list").append(tr); } }, error: function (xhr) { alert("购物袋列表数据加载产生未知的异常" + xhr.status); } }); } </script>
update t_cart set num = ?, modified_user = ?, modified_time = ? where cid = ?;
select * from t_cart where cid=#{cid}
Cart findByCid(Integer cid);
<select id="findByCid">
select * from t_cart where cid=#{cid};
</select>
@Test
public void findByCid() {
System.out.println(cartMapper.findByCid(1));
}
/**
* 更新用户的购物车数据的数量
* @param cid
* @param uid
* @param username
* @return 增加成功后新的数量
*/
Integer addNum(Integer cid, Integer uid, String username);
@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; }
else if (e instanceof CartNotFoundException) {
result.setState(4007);
result.setMessage("购物车数据不存在的异常");
}
/carts/{cid}/num/add
Integer cid, HttpSession
post
JsonResult<Integer>
@RequestMapping("{cid}/num/add")
public JsonResult<Integer> addNum(@PathVariable("cid") Integer cid, HttpSession session) {
Integer data = cartService.addNum(
cid,
getuidFromSession(session),
getUsernameFromSession(session)
);
return new JsonResult<>(OK, data);
}
function addNum(cid) { $.ajax({ url: "/carts/" + cid + "/num/add", type: "post", dataType: "JSON", success: function (json) { if(json.state == 200) { $("#goodsCount" + cid).val(json.data); let price = $("#goodsPrice" + cid).html(); let totalPrice = price * json.data; $("#goodsCast" + cid).html(totalPrice); } else { alert("增加购物车数据失败," + json.message); } }, error: function (xhr) { alert("增加购物车商品数量产生未知的异常" + xhr.message); } }); }
select
cid,uid,pid,t_cart.price,t_cart.num,
t_product.title,t_product.image,t_product.price as realPrice
from
t_cart left join t_product on t_cart.pid = t_product.id
where
cid in (?,?,?)
order by
t_cart.created_time desc;
List<CartVO> findVOByCid(Integer[] cids);
<select id="findVOByCid" resultType="com.cy.store.vo.CartVO">
select
cid, uid, pid, t_cart.price, t_cart.num,
t_product.title, t_product.image, t_product.price as realPrice
from
t_cart left join t_product on t_cart.pid = t_product.id
where
cid in (
<foreach collection="array" item="cid" separator=",">
#{cid}
</foreach>
)
order by
t_cart.created_time desc;
</select>
@Test
public void findVOByCid() {
Integer[] cids = {1,2,3,4,30,20,40};
System.out.println(cartMapper.findVOByCid(cids));
}
1.没有需要进行异常的规划
2.设计业务层接口中抽象方法
List<CartVO> getVOByCid(Integer uid, Integer[] cids);
3.完成抽象方法的设计
@Override
public 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;
}
1.请求设计
/carts/list
Integer cids, HttpSession session
post
JsonResult<CartVO>
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);
}
在cart.html中有个表单,点击“结算”按钮跳转到这个页面:action=“orderConfirm.html”。在orderConfirm.html页面加入如下代码,可以使页面跳转后就加载要结算的数据。
<script type="text/javascript"> $(document).ready(function () { showCartList(); }); //展示购物车列表 function showCartList() { //清空tbody标签的数据 $("#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}/g, list[i].image); tr = tr.replace(/#{title}/g, list[i].title); tr = tr.replace(/#{price}/g, list[i].price); tr = tr.replace(/#{num}/g, list[i].num); tr = tr.replace(/#{totalPrice}/g, list[i].price*list[i].num); $("#cart-list").append(tr); allCount += list[i].num; allPrice += list[i].price * list[i].num; } $("#all-count").html(allCount); $("#all-price").html(allPrice); } }, error: function (xhr) { alert("购物袋列表数据加载产生未知的异常" + xhr.status); } }); } </script>
注:这里有个bug,当你什么都不勾选就去结算,会报错。因为controller中是需要接收参数的,但是没勾选就提交是没有带参数的,这就有问题了。所以最好在结算的时候判断一下有没有选择商品。
1.收获地址存放在一个select下拉列表中,将查询到的当前登录用户的收货地址动态的加载到这个下拉列表中。从数据库的角度,是一个select查询语句。已经编写了根据用户的uid来查询当前用户的收货地址数据。
2.orderConfirm.html页面中,收货地址数据的展示需要自动进行加载,需要将方法的逻辑放在ready()函数中。
$(document).ready(function () {
showCartList();
showAddressList();
});
3.声明和定义showAddressList()方法,方法中发送ajax请求即可。
function showAddressList() { //清空tbody标签的数据 $("#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++) { let opt = "<option value='#{aid}'>#{name} #{tag} #{provinceName}#{cityName}#{areaName}#{address} #{phone}</option>"; opt = opt.replace(/#{aid}/g, list[i].aid); opt = opt.replace(/#{name}/g, list[i].name); opt = opt.replace(/#{tag}/g, list[i].tag); opt = opt.replace(/#{provinceName}/g, list[i].provinceName); opt = opt.replace(/#{cityName}/g, list[i].cityName); opt = opt.replace(/#{areaName}/g, list[i].areaName); opt = opt.replace(/#{address}/g, list[i].address); opt = opt.replace(/#{phone}/g, list[i].phone); $("#address-list").append(opt); } } }, error: function (xhr) { alert("购物车收货地址加载产生未知的异常" + xhr.status); } }); }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。