You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将类作为Model属性传递?页面展示关联属性报错求助

订单列表展示报错问题处理

问题描述

我定义了Order类,通过model.addAttribute将其列表传递至HTML页面,期望展示order.customer.address、order.orderDetailList.product.name、order.orderDetailList.quantity属性,但运行时出现报错。

相关代码

Controller代码

@GetMapping("/orders")
public String orders(Model model, Principal principal){
    if(principal == null){
        return "redirect:/login";
    }
    List<Order> orders = orderService.getAllOrders();
    model.addAttribute("orders", orders);
}

Order实体类

public class Order {
   
    private Long id;
    // 省略其他属性
    private String orderStatus;
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "customer_id", referencedColumnName = "customer_id")
    private Customer customer;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "order")  
    private List<OrderDetail> orderDetailList;
}

OrderDetail实体类

public class OrderDetail {
    private Long id;
    private int quantity;
    private double totalPrice;
    private double unitPrice;
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id", referencedColumnName = "order_id")
    private Order order;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id", referencedColumnName = "product_id")
    private Product product;
}

Thymeleaf页面代码

<table class="table table-bordered" th:if="${size > 0}">
    <thead>
        <tr>
            <th scope="col">Order Index</th>
            <th scope="col">Order Date</th>
            <th scope="col">Order Items</th>
            <th scope="col">Delivery address</th>
            <th scope="col">Order Status</th>
        </tr>
    </thead>
    <tbody>
        <tr th:each="order : ${orders}">
            <th scope="row" th:text="${order.id}"></th>
            <td th:text="${order.orderDate}"></td>
            <td th:text="${order.orderDetailList}"></td>
            <td th:text="${order.customer.address}"></td>
            <td th:text="${order.orderStatus}"></td>
        </tr>
    </tbody>
</table>

报错原因分析

  1. 懒加载初始化异常:OrderDetail中的Product采用FetchType.LAZY懒加载,Thymeleaf页面渲染时Hibernate会话已关闭,无法初始化懒加载对象,会抛出LazyInitializationException。
  2. 订单详情展示方式错误:直接用th:text="${order.orderDetailList}"会输出List对象的toString内容,无法展示单个商品的名称和数量。
  3. 空指针风险:若订单未关联Customer,访问order.customer.address会触发NullPointerException。
  4. 属性名称不匹配:你期望的属性是order.orderDetails,但实体类中实际定义的是orderDetailList,属性名不匹配会导致取值失败。

解决方案

  1. 解决懒加载问题

    • 方式一:修改OrderDetail中Product的加载策略为FetchType.EAGER:
      @OneToOne(fetch = FetchType.EAGER)
      @JoinColumn(name = "product_id", referencedColumnName = "product_id")
      private Product product;
      
    • 方式二:在Service层使用关联查询提前加载数据,避免会话关闭后无法初始化:
      // 在OrderService的getAllOrders方法中使用JPQL
      public List<Order> getAllOrders() {
          return entityManager.createQuery(
              "SELECT o FROM Order o " +
              "JOIN FETCH o.customer " +
              "JOIN FETCH o.orderDetailList od " +
              "JOIN FETCH od.product", Order.class
          ).getResultList();
      }
      
  2. 正确展示订单详情
    修改页面中订单详情的渲染逻辑,遍历orderDetailList展示商品名称和数量:

    <td>
        <ul>
            <li th:each="detail : ${order.orderDetailList}">
                <span th:text="${detail.product.name}"></span> - 
                <span th:text="${detail.quantity}"></span> 件
            </li>
        </ul>
    </td>
    
  3. 处理空值避免空指针
    使用Thymeleaf的Elvis运算符处理可能为空的属性:

    <td th:text="${order.customer?.address ?: '无收货地址'}"></td>
    
  4. 核对属性名称
    确保页面中使用的属性名与实体类完全一致,实体类中订单详情列表是orderDetailList,不要写成orderDetails。

内容的提问来源于stack exchange,提问作者alnvalnnn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:34:51