store(商城项目)Springboot+springmvc+ajax+mybatis(15)

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. 订单-创建订单-前端页面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

饭九钦vlog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值