- 購物車表
create table 'mmall_cart'(
'id' int(11) NOT NULL AUTO_INCREMENT,
'user_id' int(11) NOT NULL COMMENT '用戶id',
'product_id' int(11) DEFAULT NULL COMMENT '商品id',
'quantity' int(11) DEFAULT NULL COMMENT '數量',
'checked' int(11) DEFAULT NULL COMMENT '是否選擇:0-未勾選,1-已勾選',
'create_time' datetime DEFAULT NULL COMMENT '創建時間',
'update_time' datetime DEFAULT NULL COMMENT '更新時間',
PRIMARY KEY ('id'),
KEY 'user_id_index' ('user_id') USING BTREE
)ENGINE=InnoDB AUTO_INCREMENT=121 DEFAULT CHARSET=utf8
- CartVo類,省略了set,get方法
public class CartVo {
private List<CartProductVo> cartProductVoList;
private BigDecimal cartTotalPrice; //購物車選中商品的總價格
private Boolean allChecked;//是否已經都勾選
private String imageHost; //商品圖片地址
}
- CartProductVo類,省略了set,get方法
public class CartProductVo {
//結合了產品和購物車的一個抽象對象
private Integer id;
private Integer userId;
private Integer productId;
private Integer quantity;//購物車中此商品的數量
private String productName; //商品名稱
private String productSubtitle; //商品副標題
private String productMainImage; //商品組圖
private BigDecimal productPrice; //商品價格
private Integer productStatus; //商品狀態
private BigDecimal productTotalPrice; //商品總價格
private Integer productStock; //商品庫存
private Integer productChecked;//此商品是否勾選
private String limitQuantity;//限制數量的一個返回結果
}
- 公共常量類
public class Const {
public static final String CURRENT_USER = "currentUser";
public static final String EMAIL="email";
public static final String USERNAME="username";
public interface Role{
int ROLE_CUSTOMER=0;//普通用戶
int ROLE_ADMIN=1;//管理員
}
public interface Cart{
int CHECKED = 1;//即購物車選中狀態
int UN_CHECKED = 0;//購物車中未選中狀態
String LIMIT_NUM_FAIL = "LIMIT_NUM_FAIL"; //庫存不充足
String LIMIT_NUM_SUCCESS = "LIMIT_NUM_SUCCESS"; //庫存充足
}
}
-
寫個私有的方法,給購物車做限制,限制購買的數量不能超過庫存量,精確商品總價。 購物車增刪改查都要用到這個方法,所以就單獨寫出這個方法供調用。
//給購物車做限制,限制購買的數量不能超過庫存量,精確商品總價
private CartVo getCartVoLimit(Integer userId) {
CartVo cartVo = new CartVo();
//用List存儲該用戶購物車裏的信息
List<Cart> cartList = cartMapper.selectByUserId(userId);
List<CartProductVo> cartProductVoList = Lists.newArrayList();
//public BigDecimal(String val),String構造器。將String表示形式轉換成BigDecimal
BigDecimal cartTotalPrice = new BigDecimal("0");
//如果該用戶購物車裏的商品不爲空,CartProductVo爲展示在前端的數據
if (CollectionUtils.isNotEmpty(cartList)) {
for (Cart cartItem : cartList) {
CartProductVo cartProductVo = new CartProductVo();
cartProductVo.setId(cartItem.getId());
cartProductVo.setProductId(cartItem.getProductId());
cartProductVo.setUserId(userId);
//查詢該商品的信息
Product product = productMapper.selectByPrimaryKey(cartItem.getProductId());
if (product != null) {
cartProductVo.setProductMainImage(product.getMainImage());
cartProductVo.setProductName(product.getName());
cartProductVo.setProductSubtitle(product.getSubtitle());
cartProductVo.setProductStatus(product.getStatus());
cartProductVo.setProductPrice(product.getPrice());
cartProductVo.setProductStock(product.getStock());
//判斷庫存
int buyLimitCount = 0;
//庫存充足,庫存的數量大於該商品在購物車裏的數量
if (product.getStock() >= cartItem.getQuantity()) {
buyLimitCount = cartItem.getQuantity();
cartProductVo.setLimitQuantity(Const.Cart.LIMIT_NUM_SUCCESS);
} else {
//庫存不充足,庫存的數量小於該商品在購物車裏的數量,就要把庫存的數量賦值給當前購物車裏的數量
buyLimitCount = product.getStock();
cartProductVo.setLimitQuantity(Const.Cart.LIMIT_NUM_FAIL);
//此時要更新數據庫中購物車該商品的數量
Cart cartForQuantity = new Cart();
cartForQuantity.setId(cartItem.getId());
cartForQuantity.setQuantity(buyLimitCount);
cartMapper.updateByPrimaryKeySelective(cartForQuantity);
}
cartProductVo.setQuantity(buyLimitCount);
//計算這個商品的總價
cartProductVo.setProductTotalPrice(BigDecimalUtil.mul(product.getPrice().doubleValue(), cartProductVo.getQuantity()));
//對這個商品進行勾選
cartProductVo.setProductChecked(cartItem.getChecked());
}
//商品如果被選中,就把該商品的價錢加起來
if (cartItem.getChecked() == Const.Cart.CHECKED) {
//購物車裏的合計總價錢
cartTotalPrice = BigDecimalUtil.add(cartTotalPrice.doubleValue(), cartProductVo.getProductTotalPrice().doubleValue());
}
cartProductVoList.add(cartProductVo);
}
}
cartVo.setCartTotalPrice(cartTotalPrice);
cartVo.setCartProductVoList(cartProductVoList);
cartVo.setAllChecked(this.getAllCheckedStatus(userId));
cartVo.setImageHost(PropertiesUtil.getProperty("ftp.server.http.prefix"));
return cartVo;
}
//購物車裏的商品是否爲全選狀態,check=1位選中狀態
private boolean getAllCheckedStatus(Integer userId) {
if (userId == null) {
return false;
}
return cartMapper.selectCartProductCheckedStatusByUserId(userId) == 0;
- 精確價格的方法,計算 價格的時候要用到
/**
* 當double必須用作BigDecimal的源時,
* 請使用Double.toString(double)轉成String,
* 然後使用String構造方法,
* 或使用BigDecimal的靜態方法valueOf
*/
public class BigDecimalUtil {
private BigDecimalUtil(){
}
public static BigDecimal add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2);
}
public static BigDecimal sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2);
}
public static BigDecimal mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2);
}
public static BigDecimal div(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2,2,BigDecimal.ROUND_HALF_UP);//四捨五入,保留2位小數
}
}
一、增加購物車
- 思路:
1、先判斷用戶是否登錄。
2、判斷購物車是否存在此商品,如果不存在此商品,就把該商品添加在購物車中,並把該商品設置爲選中狀態。如果已存在此商品,就把該商品數量修改爲原先購物車裏該商品的數量再加上要添加的商品數量。
3、調用上述所寫的購物車限制的方法,用List存儲該用戶購物車中所有的信息。foreach循環遍歷List,每遍歷一個商品就判斷它的庫存是否小於購物車該商品的數量,如果庫存 < 購物車,爲庫存不充足,就把購物車中該商品的數量修改爲庫存的數量。如果庫存 > 購物車,庫存充足則不修改。
4、計算商品的總價,商品單價*數量。計算購物車中選中商品的總價格,每個選中的商品的總價相加。
- controller(參數:商品id,商品數量)
//添加購物車
//http://localhost:8080/cart/add.do?productId=1&count=10
@RequestMapping("add.do")
@ResponseBody
public ServerResponse<CartVo> add(HttpSession session, Integer productId, Integer count){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
}
return iCartService.add(productId,count,user.getId());
}
- impl(參數:商品id,商品數量,用戶id)
超過數量會返回這樣的標識"limitQuantity",失敗的:LIMIT_NUM_FAIL, 成功的:LIMIT_NUM_SUCCESS
//往購物車中添加商品
public ServerResponse<CartVo> add(Integer productId, Integer count, Integer userId) {
if (productId == null || count == null) {
return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), ResponseCode.ILLEGAL_ARGUMENT.getDesc());
}
//先從購物車裏查看是否有該相同的商品
Cart cart = cartMapper.selectByProductIdUserId(productId, userId);
//如果沒有則新創建一個對象,在數據庫中增加該商品
if (cart == null) {
Cart cartItem = new Cart();
cartItem.setUserId(userId);
cartItem.setProductId(productId);
cartItem.setQuantity(count);
cartItem.setChecked(Const.Cart.CHECKED);//設置爲選中狀態
cartMapper.insert(cartItem);
} else {
//否則該商品早已經添加進購物車,在該商品的數量上加入剛剛所要添加的數量
count = cart.getQuantity() + count;
cart.setQuantity(count);
cartMapper.updateByPrimaryKeySelective(cart);
}
CartVo cartVo=this.getCartVoLimit(userId);
return ServerResponse.createBySuccess(cartVo);
}
二、修改購物車商品的數量
- controller(參數:商品id,數量count)
//修改購物車中某個商品
//http://localhost:8080/cart/update.do?productId=1&count=2
@RequestMapping("update.do")
@ResponseBody
public ServerResponse<CartVo> update(HttpSession session, Integer productId, Integer count){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
}
return iCartService.update(productId,count,user.getId());
- impl(參數:商品id,數量count,用戶id)
//修改購物車中的商品數量
public ServerResponse<CartVo> update(Integer productId, Integer count, Integer userId) {
if (productId == null || count == null) {
return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), ResponseCode.ILLEGAL_ARGUMENT.getDesc());
}
Cart cart = cartMapper.selectByProductIdUserId(productId, userId);
if (cart != null){
cart.setQuantity(count);
}
cartMapper.updateByPrimaryKeySelective(cart);
CartVo cartVo=this.getCartVoLimit(userId);
return ServerResponse.createBySuccess(cartVo);
}
三、刪除購物車中某個商品
- 思路:
1、因爲刪除商品可以是選中要刪除的多個商品然後一起刪除,所以用Guava的Splitter.on(",").splitToList(productIds)對商品用逗號分割存儲進List。
2、使用Mybatis中提供的foreach功能,遍歷的刪除每個商品。
- controller(參數:商品id)
//刪除購物車中某個商品
//http://localhost:8080/cart/delete_product.do?productIds=1,3
@RequestMapping("delete_product.do")
@ResponseBody
public ServerResponse<CartVo> deleteProduct(HttpSession session, String productIds){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
}
return iCartService.deleteProduct(productIds,user.getId());
}
- impl(參數:商品id,用戶id)
//購物車中刪除商品
public ServerResponse<CartVo> deleteProduct(String productIds, Integer userId) {
//例如 splitter("b=22,c=33,a=11, "),輸出{ b=22, c=33, a=11, }
List<String> productList= Splitter.on(",").splitToList(productIds);
if (CollectionUtils.isEmpty(productList)){
return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(), ResponseCode.ILLEGAL_ARGUMENT.getDesc());
}
cartMapper.deleteByUserIdProductIds(productList,userId);
CartVo cartVo=this.getCartVoLimit(userId);
return ServerResponse.createBySuccess(cartVo);
}
- Mybatis--SQL
foreach主要用於構建的in條件中,item爲每次獲取的都使用#{item}即可取到值,open="(" separator="," close=")" 的意思:以“(”開始,中間用“,”分開,以“)”結束。
<delete id="deleteByUserIdProductIds" parameterType="map">
delete from mmall_cart
where user_id=#{userId}
<if test="productIdList != null">
and product_id in
<foreach collection="productIdList" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</delete>
四、購物車列表
- controller
//展示用戶的購物車列表
@RequestMapping("list.do")
@ResponseBody
public ServerResponse<CartVo> list(HttpSession session){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
}
return iCartService.list(user.getId());
}
- impl(參數:用戶id)
//展示用戶的購物車列表
public ServerResponse<CartVo> list(Integer userId){
CartVo cartVo=this.getCartVoLimit(userId);
return ServerResponse.createBySuccess(cartVo);
}
五、選中或者取消選中某個商品
- controller(參數:商品id)
//選中某商品
//http://localhost:8080/cart/select.do?productId=1
@RequestMapping("select.do")
@ResponseBody
public ServerResponse<CartVo> selectProduct(HttpSession session,Integer productId){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
}
return iCartService.selectOrUnSelect(user.getId(),productId,Const.Cart.CHECKED);
}
- controller(參數:商品id)
//取消選中的商品
//http://localhost:8080/cart/un_select.do?productId=1
@RequestMapping("un_select.do")
@ResponseBody
public ServerResponse<CartVo> unSelectProduct(HttpSession session,Integer productId){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
}
return iCartService.selectOrUnSelect(user.getId(),productId,Const.Cart.UN_CHECKED);
}
選中或者取消選中某個商品的impl一樣
- impl(用戶id,商品id,是否選中標誌checked)
//選中或者取消某個選中的商品
public ServerResponse<CartVo> selectOrUnSelect(Integer userId,Integer productId,Integer checked){
cartMapper.checkedOrUncheckedProduct(productId,userId,checked);
return list(userId);
}
六、購物車全選或者取消全選
- controller
//購物車全選
@RequestMapping("select_all.do")
@ResponseBody
public ServerResponse<CartVo> selectAll(HttpSession session){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
}
return iCartService.selectAllOrUnSelectAll(user.getId(),Const.Cart.CHECKED);
}
- controller
//購物車取消全選
@RequestMapping("un_select_all.do")
@ResponseBody
public ServerResponse<CartVo> unSelectAll(HttpSession session){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
}
return iCartService.selectAllOrUnSelectAll(user.getId(),Const.Cart.UN_CHECKED);
}
購物車全選或者取消全選impl一樣
- impl(參數:用戶id,是否選中標誌checked)
//全選或者取消全選
public ServerResponse<CartVo> selectAllOrUnSelectAll(Integer userId,Integer checked){
cartMapper.checkedOrUncheckedProductAll(userId,checked);
CartVo cartVo=getCartVoLimit(userId);
return ServerResponse.createBySuccess(cartVo);
}
七、獲取購物車中商品的數量
- controller(參數:用戶id)
//獲取購物車中商品的數量
@RequestMapping("get_cart_product_count.do")
@ResponseBody
public ServerResponse<Integer> getCartProductCount(HttpSession session){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if (user == null){
return ServerResponse.createBySuccess(0);
}
return iCartService.getCartProductCount(user.getId());
}
- impl(參數:用戶id)
// 獲取購物車中商品的數量
public ServerResponse<Integer> getCartProductCount(Integer userId){
if (userId == null){
return ServerResponse.createBySuccess(0);
}
return ServerResponse.createBySuccess(cartMapper.selectCartProductCount(userId));
}
八、Mybatis--Mapper.java
public interface CartMapper {
int deleteByPrimaryKey(Integer id);
int insert(Cart record);
int insertSelective(Cart record);
Cart selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(Cart record);
int updateByPrimaryKey(Cart record);
//在購物車裏增加商品
Cart selectByProductIdUserId(@Param(value = "productId")Integer productId,@Param(value = "userId") Integer userId);
//列出某用戶購物車裏的商品
List<Cart> selectByUserId(@Param(value = "userId") Integer userId);
//某用戶購物車中選中的商品
int selectCartProductCheckedStatusByUserId(@Param(value = "userId") Integer userId);
//購物車中刪除某商品
int deleteByUserIdProductIds(@Param(value = "productIdList")List<String> productIdList,@Param(value = "userId") Integer userId);
//選中或者取消選中某商品
int checkedOrUncheckedProduct(@Param(value = "productId")Integer productId,@Param(value = "userId") Integer userId,@Param(value = "checked")Integer checked);
//全選或者取消全選
int checkedOrUncheckedProductAll(@Param(value = "userId") Integer userId,@Param(value = "checked")Integer checked);
// 獲取購物車中商品的數量
int selectCartProductCount(@Param(value = "userId") Integer userId);
//從購物車中獲取到被勾選的商品下訂單
List<Cart> selectCheckedCartByUserId(@Param("userId") Integer userId);
}
九、Mybatis--Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mmall.dao.CartMapper" >
<resultMap id="BaseResultMap" type="com.mmall.pojo.Cart" >
<constructor >
<idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="user_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="product_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="quantity" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="checked" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="create_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="update_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
</constructor>
</resultMap>
<sql id="Base_Column_List" >
id, user_id, product_id, quantity, checked, create_time, update_time
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from mmall_cart
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from mmall_cart
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.mmall.pojo.Cart" >
insert into mmall_cart (id, user_id, product_id,
quantity, checked, create_time,
update_time)
values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{productId,jdbcType=INTEGER},
#{quantity,jdbcType=INTEGER}, #{checked,jdbcType=INTEGER}, now(),
now())
</insert>
<insert id="insertSelective" parameterType="com.mmall.pojo.Cart" >
insert into mmall_cart
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="userId != null" >
user_id,
</if>
<if test="productId != null" >
product_id,
</if>
<if test="quantity != null" >
quantity,
</if>
<if test="checked != null" >
checked,
</if>
<if test="createTime != null" >
create_time,
</if>
<if test="updateTime != null" >
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="userId != null" >
#{userId,jdbcType=INTEGER},
</if>
<if test="productId != null" >
#{productId,jdbcType=INTEGER},
</if>
<if test="quantity != null" >
#{quantity,jdbcType=INTEGER},
</if>
<if test="checked != null" >
#{checked,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
now(),
</if>
<if test="updateTime != null" >
now(),
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.mmall.pojo.Cart" >
update mmall_cart
<set >
<if test="userId != null" >
user_id = #{userId,jdbcType=INTEGER},
</if>
<if test="productId != null" >
product_id = #{productId,jdbcType=INTEGER},
</if>
<if test="quantity != null" >
quantity = #{quantity,jdbcType=INTEGER},
</if>
<if test="checked != null" >
checked = #{checked,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null" >
update_time = now(),
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.mmall.pojo.Cart" >
update mmall_cart
set user_id = #{userId,jdbcType=INTEGER},
product_id = #{productId,jdbcType=INTEGER},
quantity = #{quantity,jdbcType=INTEGER},
checked = #{checked,jdbcType=INTEGER},
create_time = #{createTime,jdbcType=TIMESTAMP},
update_time = now()
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectByProductIdUserId" parameterType="map" resultMap="BaseResultMap">
select <include refid="Base_Column_List"></include>
from mmall_cart
where user_id=#{userId} and product_id=#{productId}
</select>
<select id="selectByUserId" parameterType="int" resultMap="BaseResultMap">
select <include refid="Base_Column_List"></include>
from mmall_cart
where user_id=#{userId}
</select>
<select id="selectCartProductCheckedStatusByUserId" resultType="int" parameterType="int">
select count(1)
from mmall_cart
where user_id=#{userId} and checked=0
</select>
<delete id="deleteByUserIdProductIds" parameterType="map">
delete from mmall_cart
where user_id=#{userId}
<if test="productIdList != null">
and product_id in
<foreach collection="productIdList" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</delete>
<update id="checkedOrUncheckedProduct" parameterType="map">
update mmall_cart
set checked=#{checked},update_time=now()
where user_id=#{userId} and product_id=#{productId}
</update>
<update id="checkedOrUncheckedProductAll" parameterType="map">
update mmall_cart
set checked=#{checked},update_time=now()
where user_id=#{userId}
</update>
<select id="selectCartProductCount" parameterType="int" resultType="int">
select IFNULL(sum(quantity),0) as count from mmall_cart
where user_id=#{userId}
</select>
<select id="selectCheckedCartByUserId" parameterType="int" resultMap="BaseResultMap">
select <include refid="Base_Column_List"></include>
from mmall_cart
where checked=1 and userId=#{userId}
from
</select>
</mapper>