购物商城shopping连载(11)

本文详细介绍了购物商城的订单模块,包括订单类的创建与配置,如何从购物车提交订单并跳转到订单页面,订单数据的显示,以及如何根据订单编号查询订单。在订单表与商品表的多对多关系中,通过中间表实现关联,并讨论了级联保存的重要性。此外,还展示了如何根据用户ID查询个人订单。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

订单模块类创建及配置

购物完成之后,提交订单,生成一个订单
订单表和商品的关系:
订单和商品的关系是多对多,一个订单可以有多个商品,一个商品可以属于多个订单。
如果是多对多的关系,那么建表的时候应该建第三张表(中间表),存订单表和商品表的id。
中间表:订单项表:

这里写图片描述

订单表和商品表是多对多关系,可以通过两个一对多的形式完成多对多的关联关系。即商品对订单项是一对多,订单对订单项也是一对多,两个表对中间表的一对多关系相当于商品和订单表的多对多关系。

这里写图片描述

说下这样处理的好处,如果你把商品表和订单表的关系创建成多对多的关系,中间表只会维护商品id和订单id,中间的订单表的其他字段是不会自动维护的,如果配成一对多,其他自动就可以自动维护。

订单表:

/***
 * 订单表
 * 
 */
@SuppressWarnings("serial")
public class Order implements Serializable {
    private long oid;// 订单id
    private Double total; // 总计
    private Date orderTime;// 订单下单时间
    private int state; // 订单状态
    private String name;// 用户名
    private String addr; // 地址
    private String phone;// 用户电话
    // 订单所属用户
    private User user;
    // 订单中包含多个订单项
    private Set<OrderItem> orderItems = new HashSet<OrderItem>();
    //省略setter getter方法

OrderItem订单项表:

@SuppressWarnings("serial")
public class OrderItem implements Serializable{
    private long itemid; //订单项id
    private int count; //订单数量
    private Double subtotal; //订单小计
    // 商品对象
    private Product product;
    // 订单对象
    private Order order;
    //省略setter getter方法

Order.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.shopping.order.entity.Order" table="orders">
        <id name="oid">
            <generator class="native"/>
        </id>

        <property name="total"/>
        <property name="orderTime"/>
        <property name="state"/>
        <property name="name"/>
        <property name="phone"/>
        <property name="addr"/>

        <!-- 订单与用户关联配置 -->
        <!-- 一个用户有多个订单 ,多个订单属于一个用户-->
        <many-to-one name="user" lazy="false" class="com.shopping.user.entity.User" column="uid"/>

        <!-- 订单与订单项关联配置 -->
        <!-- 一个订单包含多个订单项 -->
        <set name="orderItems" lazy="false" cascade="save-update">
            <key column="oid"/>
            <one-to-many class="com.shopping.order.entity.OrderItem"/>
        </set>
    </class>
</hibernate-mapping>

OrderItem.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.shopping.order.entity.OrderItem" table="orderitem">
        <id name="itemid">
            <generator class="native"/>
        </id>

        <property name="count"/>
        <property name="subtotal"/>

        <!-- 订单项是多方, product是一方-->
        <many-to-one name="product" lazy="false" class="com.shopping.product.entity.Product" column="pid"></many-to-one>

        <!-- 订单项是多方 ,order是一方-->
        <many-to-one name="order" class="com.shopping.order.entity.Order" column="oid"/>
    </class>
</hibernate-mapping>

这里写图片描述

这里说明一下,在Oder中用到了User对象,表示多个订单属于一个用户,如果你不需要在User中需要Order,则不用写以下代码:

Set<Order> orders = new HashSet<Order>();
//用到就写,不用就可以不用写,不会影响建表

订单模块跳转到订单页面

在购物车页面点击提交订单的时候:

这里写图片描述

应该跳转到订单页面,订单页面见上面第一张图。

                        <a href="${ pageContext.request.contextPath }/order_saveOrder.do" id="submit" class="submit">提交订单</a>

OrderAction:

package com.shopping.order.action;

import org.hibernate.criterion.Order;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.shopping.base.BaseAction;

@SuppressWarnings("serial")
@Controller
@Scope("prototype")
public class OrderAction extends BaseAction<Order> {


    public String saveOrder(){
        System.out.println("order..");
        return "saveSuccess";
    }
}

跳转成功。
提交订单,1.把订单和订单项保存到数据库。2.把订单信息显示到页面上
补全saveOrder方法:

    public String saveOrder() {
        // System.out.println("order..");
        // 1.保存数据到数据库
        // 订单数据的补全
        model.setOrderTime(new Date());// 系统当前时间
        model.setState(1); // 1:未付款 2:付款未发货 3:发货,没有确认收获 4:确认收获
        // 总计是购物车中的总计
        Cart cart = (Cart) ServletActionContext.getRequest().getSession()
                .getAttribute("cart");
        if (cart == null) {
            addActionMessage("亲!您还没有购物,请前去购物");
            return "msg";
        }
        model.setTotal(cart.getTotal());
        // 设置订单中的订单项
        // 订单项在购物车中
        for (CartItem cartItem : cart.getCartItems()) {
            // 订单项的信息从购物项获得的.
            OrderItem orderItem = new OrderItem();
            orderItem.setCount(cartItem.getCount());
            orderItem.setSubtotal(cartItem.getSubtotal());
            orderItem.setProduct(cartItem.getProduct());
            orderItem.setOrder(model);

            model.getOrderItems().add(orderItem);
        }
        // 设置订单关联的客户:
        User user = (User) ServletActionContext.getRequest().getSession()
                .getAttribute("user");
        if(user==null){
            addActionMessage("亲,您还未登录,请前去登录");
            return "loginUI";
        }
        model.setUser(user);

        orderService.save(model);
        // 2.将订单数据显示在页面
        return "saveSuccess";
    }

1.补全订单表:
(1)补全下单时间:model.setOrderTime(new Date());// 系统当前时间
(2)补全订单状态(1:未付款 2:付款未发货 3:发货,没有确认收获 4:确认收获),初始状态都是1:model.setState(1);
(3)订单的总金额就是购物车的总金额:怎么获得购物车信息?因为之前购物车存入到session中 ,所以直接从session中获得购物车:

Cart cart = (Cart) ServletActionContext.getRequest().getSession()
                .getAttribute("cart");
        if (cart == null) {
            addActionMessage("亲!您还没有购物,请前去购物");
            return "msg";
        }
        //设置总计
        model.setTotal(cart.getTotal());

(4)补全订单中的订单项(该订单项就是购物项),所以遍历购物车中的订单项项集合

for (CartItem cartItem : cart.getCartItems()) {
            // 订单项的信息从购物项获得的.
            OrderItem orderItem = new OrderItem();
            orderItem.setCount(cartItem.getCount());
            orderItem.setSubtotal(cartItem.getSubtotal());
            orderItem.setProduct(cartItem.getProduct());
            orderItem.setOrder(model);

            //把订单项放入订单中
            model.getOrderItems().add(orderItem);
        }

(5)订单所属用户:要想购物必须登录

User user = (User) ServletActionContext.getRequest().getSession()
                .getAttribute("user");
        if(user==null){
            addActionMessage("亲,您还未登录,请前去登录");
            return "loginUI";
        }
        model.setUser(user);

未登录则先去登录
(6)保存订单到数据库

orderService.save(model);
return "saveSuccess";

这里重点提一下
我们一点保存订单,同时也要把订单项进行保存,这就涉及到一个级联,设置订单配置文件的时候应该设置好级联,否则在你save订单的时候还得save订单项

<set name="orderItems" lazy="false" cascade="save-update">

以前曾用过级联删除,删除一个部门的时候同时删除这个部门的下级部门。用的是cascade="delete"
测试:
未登录添加购物车提交时会直接转到登录页面!ok
登录状态,提交订单,保存成功
订单表:

这里写图片描述

订单项表:

这里写图片描述

订单模块订单数据的显示

把订单对象现在在页面上,通过值栈进行显示。
(Order显示的对象就是模型驱动的使用的对象,就在栈顶,所以也不用把它再次放入值栈中)

    <s:iterator value="model.orderItems" var="item">
    <tr>
                            <td width="60"><input type="hidden" name="id" value="22" />
                                <img src="${ pageContext.request.contextPath }/<s:property value="#item.product.image" />" />
                            </td>
                            <td><a target="_blank"><s:property value="#item.product.pname" />
                            </a>
                            </td>
                            <td><s:property value="#item.product.shop_price" /></td>
                            <td class="quantity" width="60">
                            <input type="text"
                                name="count" value="1" maxlength="4" />
                                <div>
                                    <span class="increase">&nbsp;</span> <span class="decrease">&nbsp;</span>
                                </div>
                            </td>
                            <td width="140"><span class="subtotal">
                                <s:property value="#item.subtotal" />
                            </span>
                            </td>
                            <td><a href="./cart_removeCart.action?pid=1" class="delete">删除</a>
                            </td>
                        </tr>
                    </s:iterator>

用户信息:

<p>
                        收货地址:<input name="addr" type="text" value="<s:property value="model.user.addr" />" style="width:350px" />
                        <br /> 收货人&nbsp;&nbsp;&nbsp;:<input name="username" type="text"
                            value="<s:property value="model.user.name" />" style="width:150px" /> <br /> 联系方式:<input name="phone"
                            type="text" value="<s:property value="model.user.phone" />" style="width:150px" />

                    </p>

这里写图片描述

订单模块显示:
通过模型驱动的对象将数据传递到页面(值栈)

我的订单

这里写图片描述

根据用户id查询我的所有订单

<a href="${ pageContext.request.contextPath }/order_findMyOrders.do?
                myid=<s:property value="#session.user.uid"/>&page=1">我的订单</a>

属性驱动获得uid

    //接收page参数
    private int page ;
    //省略setter getter方法

findMyOrders方法:

// 通过用户id查询我的所有订单
    public String findMyOrders() {
        // 此用户id也可用从session中获取
        User user = (User) ServletActionContext.getRequest().getSession().getAttribute("user");
        long myid = user.getUid();
        PageBean<Order> pageBean = orderService.queryAllOrdersByMyId(myid,page);
        //保存到值栈
        ActionContext.getContext().getValueStack().set("pageBean", pageBean);
        return "findMyOrders";
    }

service层:queryAllOrdersByMyId

/***
     * 通过id
     * 
     * @param myid
     * @return
     */
    PageBean<Order> queryAllOrdersByMyId(long myid, int page);

实现类:

package com.shopping.order.service.impl;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.shopping.base.BaseDaoImpl;
import com.shopping.order.entity.Order;
import com.shopping.order.service.OrderService;
import com.shopping.utils.PageBean;

@Transactional
@Service
public class OrderServiceImpl extends BaseDaoImpl<Order> implements
        OrderService {

    @Override
    public PageBean<Order> queryAllOrdersByMyId(long myid, int page) {
        PageBean<Order> pageBean = new PageBean<Order>();
        // 每页显示的个数
        int limit = 5;
        pageBean.setLimit(limit);
        // 当前页
        pageBean.setPage(page);

        // 查询的总个数
        int totalCount = 0;
        totalCount = findCounts(myid);
        pageBean.setTotalCount(totalCount);

        // 设置总页数
        int totalPage = 0;
        if (totalCount % limit == 0) {
            totalPage = totalCount / limit;
        } else {
            totalPage = totalCount / limit + 1;
        }
        pageBean.setTotalPage(totalPage);

        // 设置返回的商品集合
        int begin = (page - 1) * limit;
        List<Order> list = queryAllOrders(myid, begin, limit);
        pageBean.setList(list);

        return pageBean;

    }

    @SuppressWarnings("unchecked")
    private List<Order> queryAllOrders(long myid, int begin, int limit) {
        List<Order> oList = sessionFactory.getCurrentSession()
                //按时间倒序排序
        .createQuery("from Order o where o.user.uid=? order by orderTime desc")
        .setParameter(0, myid)
        .setFirstResult(begin)
        .setMaxResults(limit)
        .list();
        if(oList!=null&&oList.size()>0){
            return oList; 
        }
        return null;
    }

    private int findCounts(long myid) {
        int count = sessionFactory.getCurrentSession()
        .createQuery("from Order o where o.user.uid=?")
        .setParameter(0, myid)
        .list().size();
        if(count>0){
            return count;
        }
        return 0;
    }

}

JSP:

<tbody>
                    <s:iterator var="order" value="pageBean.list">
                        <tr>
                            <th colspan="5">订单编号:<s:property value="#order.oid" />&nbsp;&nbsp;&nbsp;&nbsp;订单金额:<font
                                color="red"><s:property value="#order.total" />
                            </font>
                            &nbsp;&nbsp;&nbsp;&nbsp;<font color="red">
                                <s:if test="#order.state == 1">
                                    <a href="${ pageContext.request.contextPath }/order_findByOid.do?oid=<s:property value="#order.oid" />">付款</a>
                                </s:if>
                                <s:if test="#order.state == 2">
                                    已付款
                                </s:if>
                                <s:if test="#order.state == 3">
                                    <a href="${ pageContext.request.contextPath }/order_updateState.do?oid=<s:property value="#order.oid" />">确认收货</a>
                                </s:if>
                                <s:if test="#order.state == 4">
                                    交易成功
                                </s:if>
                            </font>
                            </th>
                        </tr>
                        <tr>
                            <th>图片</th>
                            <th>商品</th>
                            <th>价格</th>
                            <th>数量</th>
                            <th>小计</th>
                        </tr>
                        <s:iterator var="orderItem" value="#order.orderItems">
                            <tr>
                                <td width="60"><img
                                    src="${ pageContext.request.contextPath }/<s:property value="#orderItem.product.image"/>" />
                                </td>
                                <td><s:property value="#orderItem.product.pname" /></td>
                                <td><s:property value="#orderItem.product.shop_price" /></td>
                                <td class="quantity" width="60"><s:property
                                        value="#orderItem.count" /></td>
                                <td width="140"><span class="subtotal"><s:property
                                            value="#orderItem.subtotal" />
                                </span></td>
                            </tr>
                        </s:iterator>
                    </s:iterator>
                    <tr>
                        <th colspan="5">
                        <div class="pagination">
                            <span><s:property value="pageBean.page" />/<s:property
                                value="pageBean.totalPage" /></span>
                                <s:if test="pageBean.page != 1">
                                <a
                                    href="${ pageContext.request.contextPath }/order_findMyOrders.do?page=1"
                                    class="firstPage">&nbsp;</a>
                                <a
                                    href="${ pageContext.request.contextPath }/order_findMyOrders.do?page=<s:property value="pageBean.page-1"/>"
                                    class="previousPage">&nbsp;</a>
                            </s:if> <s:iterator var="i" begin="1" end="pageBean.totalPage">
                                <s:if test="pageBean.page != #i">
                                    <a
                                        href="${ pageContext.request.contextPath }/order_findMyOrders.do?page=<s:property value="#i"/>"><s:property
                                            value="#i" />
                                    </a>
                                </s:if>
                                <s:else>
                                    <span class="currentPage"><s:property value="#i" />
                                    </span>
                                </s:else>
                            </s:iterator> <s:if test="pageBean.page != pageBean.totalPage">
                                <a class="nextPage"
                                    href="${ pageContext.request.contextPath }/order_findByUid.action?page=<s:property value="pageBean.page+1"/>">&nbsp;</a>
                                <a class="lastPage"
                                    href="${ pageContext.request.contextPath }/order_findByUid.action?page=<s:property value="pageBean.totalPage"/>">&nbsp;</a>
                            </s:if>
                            </div>
                            </th>
                    </tr>
                </tbody>

订单模块根据订单编号查询订单

什么意思类?就是点击上面的付款,通过订单id查询此订单。
1.点击“付款”跳转到付款界面
2.通过订单id查询此订单

// 根据订单的ID查询订单
    public String findByOid() {
        //model在模型驱动中,在栈顶
        model = orderService.getById(model.getOid());
        return "findByOidSuccess";
    }
<!-- 订单模块 -->
        <action name="order_*" method="{1}" class="orderAction">
            <result name="saveSuccess">/WEB-INF/jsp/order.jsp</result>
            <result name="loginUI" type="redirectAction">
                <param name="actionName">user_loginUI</param>
            </result>
            <result name="msg" type="redirectAction">
                <param name="actionName">index_shopping</param>
            </result>
            <result name="findMyOrders">/WEB-INF/jsp/myOrderList.jsp</result>
            <result name="findByOidSuccess">/WEB-INF/jsp/order.jsp</result>
            <result name="deleteMyOrderSuccess" type="redirectAction">order_findMyOrders</result>
        </action>`这里写代码片`

OrderAction:

package com.shopping.order.action;

import java.util.Date;

import org.apache.struts2.ServletActionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionContext;
import com.shopping.base.BaseAction;
import com.shopping.cart.entity.Cart;
import com.shopping.cart.entity.CartItem;
import com.shopping.order.entity.Order;
import com.shopping.order.entity.OrderItem;
import com.shopping.user.entity.User;
import com.shopping.utils.PageBean;

@SuppressWarnings("serial")
@Controller
@Scope("prototype")
public class OrderAction extends BaseAction<Order> {

    // 接收page参数
    private int page;

    public String saveOrder() {
        // System.out.println("order..");
        // 1.保存数据到数据库
        // 订单数据的补全
        model.setOrderTime(new Date());// 系统当前时间
        model.setState(1); // 1:未付款 2:付款未发货 3:发货,没有确认收获 4:确认收获
        // 总计是购物车中的总计
        Cart cart = (Cart) ServletActionContext.getRequest().getSession()
                .getAttribute("cart");
        if (cart == null) {
            addActionMessage("亲!您还没有购物,请前去购物");
            return "msg";
        }
        model.setTotal(cart.getTotal());
        // 设置订单中的订单项
        // 订单项在购物车中
        for (CartItem cartItem : cart.getCartItems()) {
            // 订单项的信息从购物项获得的.
            OrderItem orderItem = new OrderItem();
            orderItem.setCount(cartItem.getCount());
            orderItem.setSubtotal(cartItem.getSubtotal());
            orderItem.setProduct(cartItem.getProduct());
            orderItem.setOrder(model);
            // 把订单项放入订单中
            model.getOrderItems().add(orderItem);
        }
        // 设置订单关联的客户:
        User user = (User) ServletActionContext.getRequest().getSession()
                .getAttribute("user");
        if (user == null) {
            this.addActionMessage("亲,您还未登录,请前去登录");
            return "loginUI";
        }
        model.setUser(user);

        orderService.save(model);
        // 2.将订单数据显示在页面

        return "saveSuccess";
    }

    // 通过用户id查询我的所有订单
    public String findMyOrders() {
        // 此用户id也可用从session中获取
        User user = (User) ServletActionContext.getRequest().getSession()
                .getAttribute("user");
        long myid = user.getUid();
        PageBean<Order> pageBean = orderService
                .queryAllOrdersByMyId(myid, page);
        // 保存到值栈
        ActionContext.getContext().getValueStack().set("pageBean", pageBean);
        return "findMyOrders";
    }

    // 根据订单的ID查询订单
    public String findByOid() {
        //model在模型驱动中,在栈顶
        model = orderService.getById(model.getOid());
        return "findByOidSuccess";
    }

    //删除订单
    public String deleteMyOrder(){
        orderService.delete(model.getOid());
        return "deleteMyOrderSuccess";
    }


    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值