78. 创建订单表与订单商品表
CREATE TABLE t_order (
oid INT AUTO_INCREMENT COMMENT '订单id',
uid INT COMMENT '归属用户',
recv_name VARCHAR(20) COMMENT '收货人姓名',
recv_phone VARCHAR(20) COMMENT '收货人电话',
recv_province VARCHAR(20) COMMENT '收货地所在省',
recv_city VARCHAR(20) COMMENT '收货地所在市',
recv_area VARCHAR(20) COMMENT '收货地所在区',
recv_address VARCHAR(50) COMMENT '详细地址',
total_price BIGINT COMMENT '订单总价',
order_time DATETIME COMMENT '下单时间',
pay_time DATETIME COMMENT '支付时间',
status INT COMMENT '订单状态:0-未支付,1-已支付,2-已取消,3-已关闭',
created_user VARCHAR(20) COMMENT '创建人',
created_time DATETIME COMMENT '创建时间',
modified_user VARCHAR(20) COMMENT '最后修改人',
modified_time DATETIME COMMENT '最后修改时间',
PRIMARY KEY (oid)
) DEFAULT CHARSET=UTF8MB4;
CREATE TABLE t_order_item (
id INT AUTO_INCREMENT COMMENT '订单商品id',
oid INT COMMENT '归属订单',
pid INT COMMENT '商品id',
title VARCHAR(100) COMMENT '商品标题',
image VARCHAR(500) COMMENT '商品图片',
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 (id)
) DEFAULT CHARSET=UTF8MB4;
79. 创建实体类
创建cn.tedu.store.entity.Order
实体类,继承自BaseEntity
:
/**
* 订单数据的实体类
*/
public class Order extends BaseEntity {
private static final long serialVersionUID = -3216224344757796927L;
private Integer oid;
private Integer uid;
private String recvName;
private String recvPhone;
private String recvProvince;
private String recvCity;
private String recvArea;
private String recvAddress;
private Long totalPrice;
private Date orderTime;
private Date payTime;
private Integer status;
}
创建cn.tedu.store.entity.OrderItem
实体类,继承自BaseEntity
:
/**
* 订单中的商品记录的实体类
*/
public class OrderItem extends BaseEntity {
private static final long serialVersionUID = -8879247924788259070L;
private Integer id;
private Integer oid;
private Integer pid;
private String title;
private String image;
private Long price;
private Integer num;
}
80. 订单-创建订单-持久层
(a) 规划所需要执行的SQL语句
创建时,需要向2张数据表分别插入数据,需要执行的SQL语句大致是:
insert into t_order (除了oid以外的字段列表) values (匹配的值列表);
insert into t_order_item (除了id以外的字段列表) values (匹配的值列表);
(b) 在接口中添加抽象方法
先创建cn.tedu.store.mapper.OrderMapepr
接口文件,并在接口中添加抽象方法:
Integer insertOrder(Order order);
Integer insertOrderItem(OrderItem orderItem);
(c) 在XML中配置抽象方法对应的SQL语句
复制得到OrderMapper.xml文件,修改根节点的namespace
属性对应以上接口,然后配置映射:
<mapper namespace="cn.tedu.store.mapper.OrderMapper">
<!-- 插入订单数据 -->
<!-- Integer insertOrder(Order order) -->
<insert id="insertOrder"
useGeneratedKeys="true"
keyProperty="oid">
INSERT INTO t_order (
uid,
recv_name, recv_phone,
recv_province, recv_city,
recv_area, recv_address,
total_price, order_time,
pay_time, status,
created_user, created_time,
modified_user, modified_time
) VALUES (
#{uid},
#{recvName}, #{recvPhone},
#{recvProvince}, #{recvCity},
#{recvArea}, #{recvAddress},
#{totalPrice}, #{orderTime},
#{payTime}, #{status},
#{createdUser}, #{createdTime},
#{modifiedUser}, #{modifiedTime}
)
</insert>
<!-- 插入订单商品数据 -->
<!-- Integer insertOrderItem(OrderItem orderItem) -->
<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>
测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderMapperTests {
@Autowired
private OrderMapper mapper;
@Test
public void insertOrder() {
Order order = new Order();
order.setUid(1);
order.setRecvName("小王");
Integer rows = mapper.insertOrder(order);
System.err.println("rows=" + rows);
}
@Test
public void insertOrderItem() {
OrderItem orderItem = new OrderItem();
orderItem.setOid(1);
orderItem.setPid(2);
orderItem.setNum(3);
Integer rows = mapper.insertOrderItem(orderItem);
System.err.println("rows=" + rows);
}
}
81. 订单-创建订单-业务层
(a) 规划异常
暂无,不需要创建新的异常类。
(b) 在接口中添加抽象方法
创建cn.tedu.store.service.IOrderService
接口,并添加抽象方法:
Order create(Integer uid, String username, Integer aid, Integer[] cids);
(c) 在实现类中,实现抽象方法
由于后续需要根据收货地址id查询数据,所以,先在IAddressService
接口中添加:
Address getByAid(Integer aid, Integer uid);
并在AddressServiceImpl
中实现以上方法:
public Address getByAid(Integer aid, Integer uid) {
// 调用私有方法执行查询
// 判断查询结果是否为null
// 是:AddressNotFoundException
// 判断查询结果中的uid与当前登录的用户的uid是否不同
// 是:AccessDeniedException
// 将查询结果中的4个日志属性设置为null
// 返回查询结果
}
代码:
@Override
public Address getByAid(Integer aid, Integer uid) {
Address result = findByAid(aid);
if (result == null) {
throw new AddressNotFoundException(
"尝试访问的收货地址数据不存在");
}
if (!result.getUid().equals(uid)) {
throw new AccessDeniedException(
"非法访问");
}
result.setCreatedUser(null);
result.setCreatedTime(null);
result.setModifiedUser(null);
result.setModifiedTime(null);
return result;
}
测试:
@Test
public void getByAid() {
try {
Integer aid = 42;
Integer uid = 18;
Address result = service.getByAid(aid, uid);
System.err.println(result);
} catch (ServiceException e) {
System.err.println(e.getClass().getSimpleName());
System.err.println(e.getMessage());
}
}
创建cn.tedu.store.service.impl.OrderServiceImpl
类,实现IOrderService
接口,在类之前添加@Service
注解,在类中声明@Autowired private OrderMapper orderMapper;
持久层对象,声明@Autowired private IAddressService addressService;
处理收货地址数据的业务对象,声明@Autowired private ICartService cartService;
处理购物车数据的业务对象:
@Service
public class OrderServiceImpl implements IOrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private IAddressService addressService;
@Autowired
private ICartService cartService;
}
然后,将持久层中的2个方法复制到当前实现类中,改为私有方法,并实现:
/**
* 插入订单数据
* @param order 订单数据
*/
private void insertOrder(Order order) {
Integer rows = orderMapper.insertOrder(order);
if (rows != 1) {
throw new InsertException(
"插入订单数据时出现未知错误,请联系系统管理员");
}
}
/**
* 插入订单商品数据
* @param orderItem 订单商品数据
*/
private void insertOrderItem(OrderItem orderItem) {
Integer rows = orderMapper.insertOrderItem(orderItem);
if (rows != 1) {
throw new InsertException(
"插入订单商品数据时出现未知错误,请联系系统管理员");
}
}
然后,重写接口中的抽象方法:
@Transactional
public Order create(Integer uid, String username, Integer aid, Integer cids) {
// 创建当前时间对象now
// 调用IAddressService对象的getByAid(Integer aid, Integer uid)方法,根据参数aid和uid查询收货地址数据
// 调用ICartService对象的getVOByCids(Integer cids, Integer uid)方法,根据参数cids和uid查询匹配的购物车数据,得到List<CartVO>对象
// 声明变量totalPrice表示订单中商品的总价
// 遍历以上查询到的List<CartVO>对象
// -- 在totalPrice上累加商品的单价与数量的乘积
// 创建Order对象
// 补全数据:uid
// 补全数据:recv_???(通过查询到的收货地址数据)
// 补全数据:total_price(totalPrice)
// 补全数据:order_time(now)
// 补全数据:pay_time(保留为null)
// 补全数据:status(0)
// 补全数据:4条日志
// 插入订单数据:insertOrder(Order order);
// 遍历查询到的List<CartVO>对象
// -- 创建OrderItem对象
// -- 补全数据:oid(order.getOid())
// -- 补全数据:pid, title, image, price, num(均从CartVO对象中获取)
// -- 补全数据:4条日志
// -- 调用insertOrderItem(OrderItem orderItem)插入订单商品数据
// 将Order对象中的4条日志设置为null
// 返回Order对象
}
实现:
@Override
public Order create(Integer uid, String username, Integer aid, Integer[] cids) {
// 创建当前时间对象now
Date now = new Date();
// 调用IAddressService对象的getByAid(Integer aid, Integer uid)方法,根据参数aid和uid查询收货地址数据
Address address = addressService.getByAid(aid, uid);
// 调用ICartService对象的getVOByCids(Integer cids, Integer uid)方法,根据参数cids和uid查询匹配的购物车数据,得到List<CartVO>对象
List<CartVO> carts = cartService.getVOByCids(cids, uid);
// 声明变量totalPrice表示订单中商品的总价
Long totalPrice = 0L;
// 遍历以上查询到的List<CartVO>对象
for (CartVO cart : carts) {
// 在totalPrice上累加商品的单价与数量的乘积
totalPrice += cart.getRealPrice() * cart.getNum();
}
// 创建Order对象
Order order = new Order();
// 补全数据:uid
order.setUid(uid);
// 补全数据:recv_???(通过查询到的收货地址数据)
order.setRecvName(address.getName());
order.setRecvPhone(address.getPhone());
order.setRecvProvince(address.getProvinceName());
order.setRecvCity(address.getCityName());
order.setRecvArea(address.getAreaName());
order.setRecvAddress(address.getAddress());
// 补全数据:total_price(totalPrice)
order.setTotalPrice(totalPrice);
// 补全数据:order_time(now)
order.setOrderTime(now);
// 补全数据:pay_time(保留为null)
// 补全数据:status(0)
order.setStatus(0);
// 补全数据:4条日志
order.setCreatedUser(username);
order.setCreatedTime(now);
order.setModifiedUser(username);
order.setModifiedTime(now);
// 插入订单数据:insertOrder(Order order);
insertOrder(order);
// 遍历查询到的List<CartVO>对象
for (CartVO cart : carts) {
// 创建OrderItem对象
OrderItem item = new OrderItem();
// 补全数据:oid(order.getOid())
item.setOid(order.getOid());
// 补全数据:pid, title, image, price, num(均从CartVO对象中获取)
item.setPid(cart.getPid());
item.setTitle(cart.getTitle());
item.setImage(cart.getImage());
item.setPrice(cart.getRealPrice());
item.setNum(cart.getNum());
// 补全数据:4条日志
item.setCreatedUser(username);
item.setCreatedTime(now);
item.setModifiedUser(username);
item.setModifiedTime(now);
// 调用insertOrderItem(OrderItem orderItem)插入订单商品数据
insertOrderItem(item);
}
// 将Order对象中的4条日志设置为null
order.setCreatedUser(null);
order.setCreatedTime(null);
order.setModifiedUser(null);
order.setModifiedTime(null);
// 返回Order对象
return order;
}
完成后,测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderServiceTests {
@Autowired
private IOrderService service;
@Test
public void create() {
try {
Integer uid = 18;
String username = "Mario";
Integer aid = 41;
Integer[] cids = {3,4,5,6,7,8,9,10};
service.create(uid, username, aid, cids);
System.err.println("OK.");
} catch (ServiceException e) {
System.err.println(e.getClass().getSimpleName());
System.err.println(e.getMessage());
}
}
}
82. 订单-创建订单-控制器
(a) 处理异常
(b) 设计请求
请求路径:
请求参数:
请求方式:
响应结果:
(c) 处理请求
83. 订单-创建订单-前端页面
来源:CSDN
作者:撒向星空的画板
链接:https://blog.csdn.net/wtfsb/article/details/104055119