订单模块

数据库表创建

image-20230814154832948

image-20230814154847205

订单实体类创建

com.bang.store.pojo包下新建对应的实体类OrderOrderItem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.bang.store.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.Date;

@Data
@ToString(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class Order extends BasePojo{
Integer oid;
Integer uid;
String recvName;
String recvPhone;
String recvProvince;
String recvCity;
String recvArea;
String recvAddress;
Long totalPrice;
Integer status;
Date orderTime;
Date payTime;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.bang.store.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class OrderItem extends BasePojo{
Integer id;
Integer oid;
Integer pid;
String title;
String image;
Long price;
Integer num;
}

持久层

规划需要执行的SQL语句

创建订单的过程本质是一种数据插入的操作,即insert语句

1.数据插入订单表t_order

1
2
3
4
5
insert into t_order(uid,recv_name,recv_phone,recv_province,recv_city,recv_area
,recv_address,recv_price,total_price,status,
order_time,pay_time
,created_user,created_time,modified_user,modified_time)
values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);

2.数据插入订单项表t_order_item

1
insert into t_order_item(oid,pid,title,image,price,num,created_user,created_time,modified_user,modified_time) values(?,?,?,?,?,?,?,?,?,?);

接口和抽象方法

创建订单的持久层接口OrderMapper,在其中编写对应的抽象方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.bang.store.mapper;

import com.bang.store.pojo.Order;
import com.bang.store.pojo.OrderItem;

/**
* 订单功能持久层接口
*/
public interface OrderMapper {
/**
* 将数据插入订单数据库表
* @param order 订单数据对象
* @return 受影响行数
*/
Integer insertOrder(Order order);

/**
* 数据插入订单项数据库表
* @param orderItem 订单项数据对象
* @return 受影响行数
*/
Integer insertOrderItem(OrderItem orderItem);

}

SQL映射文件配置

新建映射文件OrderMapper.xml,在其中编写订单相关的SQL映射语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bang.store.mapper.OrderMapper">

<resultMap id="orderPojoMap" type="com.bang.store.pojo.Order">
<id column="oid" property="oid"/>
<result column="recv_name" property="recvName"/>
<result column="recv_phone" property="recvPhone"/>
<result column="recv_province" property="recvProvince"/>
<result column="recv_city" property="recvCity"/>
<result column="recv_area" property="recvArea"/>
<result column="recv_address" property="recvAddress"/>
<result column="total_price" property="totalPrice"/>
<result column="order_time" property="orderTime"/>
<result column="pay_time" property="payTime"/>
<result property="createUser" column="create_user"/>
<result property="createTime" column="create_time"/>
<result property="modifiedUser" column="modified_user"/>
<result property="modifiedTime" column="modified_time"/>
</resultMap>


<resultMap id="orderItemPojoMap" type="com.bang.store.pojo.OrderItem">
<id column="id" property="id"/>
<result property="createUser" column="create_user"/>
<result property="createTime" column="create_time"/>
<result property="modifiedUser" column="modified_user"/>
<result property="modifiedTime" column="modified_time"/>
</resultMap>

<insert id="insertOrder" useGeneratedKeys="true" keyProperty="oid">
insert into t_order(uid,recv_name,recv_phone,recv_province,recv_city,recv_area
,recv_address,recv_price,total_price,status,
order_time,pay_time
,created_user,created_time,modified_user,modified_time)
values(#{uid},#{recvName},#{recvPhone},#{recvProvince},#{recvCity},#{recvArea},#{recvAddress},#{recvPrice}
,#{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>

单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.bang.store.mapper;

import com.bang.store.pojo.Order;
import com.bang.store.pojo.OrderItem;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;
import java.util.Date;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class OrderMapperTest {
@Resource
OrderMapper orderMapper;

@Test
public void insertOrder(){
Order order = new Order();
order.setUid(2);
order.setRecvName("张佳玮");
order.setCreatedUser("admin");
order.setCreatedTime(new Date());
Integer rows = orderMapper.insertOrder(order);
System.out.println(rows);
System.out.println(order.getOid()); //可以获取对应的主键值oid
}

@Test
public void insertOrderItem(){
OrderItem orderItem = new OrderItem();
orderItem.setOid(1);
orderItem.setPid(2);
orderItem.setTitle("测试用例");
Integer rows = orderMapper.insertOrderItem(orderItem);
System.out.println(rows);
}
}

业务层

规划异常

插入语句异常类,InsertException在前面的功能模块中已经定义过了

接口和抽象方法

1.用户收货地址数据,需要依赖于前端页面传递过来的aid,所以首先对于IAddressService接口新增业务方法getByAid

1
2
3
4
5
6
7
/**
* 根据aid查询对应收货地址数据
* @param aid 地址id
* @param uid 用户id
* @return 收货地址对象
*/
Address getByAid(Integer aid,Integer uid);

2.创建订单业务层接口IOrderService,在其中申明对应的抽象方法

1
2
3
4
5
6
7
8
9
/**
* 创建订单
* @param uid 用户id
* @param username 用户名
* @param aid 用户地址id
* @param cids 用户结算订单购物车商品id列表
* @return 订单数据
*/
Address creatOrder(Integer uid,String username,Integer aid,Integer[] cids);

抽象方法实现

1.在AddressServiceImpl中编写getByAid抽象方法的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.bang.store.service;

import com.bang.store.pojo.Address;
import com.bang.store.pojo.Order;

/**
* 订单业务层接口
*/
public interface IOrderService {

/**
* 创建订单
* @param uid 用户id
* @param username 用户名
* @param aid 用户地址id
* @param cids 用户结算订单购物车商品id列表
* @return 订单数据
*/
Order creatOrder(Integer uid, String username, Integer aid, Integer[] cids);
}

2.创建IOrderService的实现类OrderServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package com.bang.store.service.impl;

import com.bang.store.mapper.OrderMapper;
import com.bang.store.pojo.Address;
import com.bang.store.pojo.Order;
import com.bang.store.pojo.OrderItem;
import com.bang.store.service.IAddressService;
import com.bang.store.service.ICartService;
import com.bang.store.service.IOrderService;
import com.bang.store.service.ex.InsertException;
import com.bang.store.vo.CartProductVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
public class OrderServiceImpl implements IOrderService {
@Resource
OrderMapper orderMapper;
@Autowired
IAddressService addressService;
@Autowired
ICartService cartService;
@Override
public Order creatOrder(Integer uid, String username, Integer aid, Integer[] cids) {
//1.创建order对象
Order order = new Order();
//2.获取地址数据
Address address = addressService.getByAid(aid, uid);
//3.获取订单商品列表数据
List<CartProductVO> cartProductVOList = cartService.getVOByCids(uid, cids);
//4.计算商品总价
Long totalPrice=0L;
for (CartProductVO cartProductVO : cartProductVOList) {
totalPrice+=cartProductVO.getCartNum()*cartProductVO.getCartPrice();
}

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.setTotalPrice(totalPrice);
order.setStatus(0);
order.setOrderTime(new Date());
// order.setPayTime(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("订单数据插入发生未知错误");
}

//5.为每个结算商品创建一个订单项
for (CartProductVO cartProductVO : cartProductVOList) {
OrderItem orderItem = new OrderItem();
orderItem.setOid(order.getOid());
orderItem.setPid(cartProductVO.getPid());
orderItem.setTitle(cartProductVO.getProductTitle());
orderItem.setImage(cartProductVO.getProductImage());
orderItem.setPrice(cartProductVO.getCartPrice());
orderItem.setNum(cartProductVO.getCartNum());
orderItem.setCreatedUser(username);
orderItem.setCreatedTime(new Date());
orderItem.setModifiedUser(username);
orderItem.setModifiedTime(new Date());
rows = orderMapper.insertOrderItem(orderItem);
if(rows!=1){
throw new InsertException("订单详细项数据插入发生未知错误");
}
}

return order;
}
}

单元测试

1
2
3
4
5
@Test
public void getByAid(){
Address address = addressService.getByAid(8,4);
System.out.println(address);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.bang.store.service;

import com.bang.store.pojo.Address;
import com.bang.store.pojo.Order;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.internal.matchers.Or;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class OrderServiceTest {

@Autowired
IOrderService orderService;
@Test
public void creatOrder(){
Integer uid=3;
String username="adminTest";
Integer aid=11;
Integer[] cids={4};
Order order = orderService.creatOrder(uid, username, aid, cids);
System.out.println(order);
}
}

控制层

异常处理

业务层无新增异常,无需新增异常处理逻辑

设计请求

1
2
3
4
request url: /order/create
request method: POST
request params: Integer aid,Integer[] cids,HttpSession session
response data: new JsonResult<Order>()

处理请求

com.bang.store.controller包下新建订单对应的控制层类OrderController,在其中编写对应处理请求方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.bang.store.controller;

import com.bang.store.pojo.Order;
import com.bang.store.service.IOrderService;
import com.bang.store.utils.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

/**
* 订单功能对应控制层类
*/
@RestController
@RequestMapping("/order")
public class OrderController extends BaseController{

@Autowired
IOrderService orderService;

@RequestMapping("/create")
public JsonResult<Order> createOrder(Integer aid, Integer[] cids, HttpSession session){
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
Order order = orderService.creatOrder(uid, username, aid, cids);
return new JsonResult<>(OK,"订单创建成功",order);
}
}

前端页面

在订单确认页面OrderConfirm.html页面点击结算按钮,向后端发送创建订单请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$("#btn-create-order").click(function () {
createOrder();
});
function createOrder() {
// alert("点击结算按钮");
$.ajax({
url: "/order/create?aid="+$("#address-list").val()+"&"+location.search.substr(1)
,type: "GET"
,dataType: "JSON"
,success: function (data){
if(data.state == 200){
alert("订单创建成功");
alert("订单号:"+data.data.oid+",支付金额:¥"+data.data.totalPrice+".收款方圆心电脑商城")
location.href="payment.html";
}else{
alert("订单创建失败 "+data.message);
}
}
,error:function (xmh){
alert("订单创建发生未知异常"+xmh.status);
}
});
}