Java Stream API & 对象列表赋值

🧾 技术详解:OrderDetailShoppingCart 对象转换

📌 背景说明

在“再来一单”业务场景中,需要将历史订单(OrderDetail)中的菜品信息重新加入当前用户的购物车(ShoppingCart)。由于两个实体类属性名称和类型基本一致,因此可以使用 Spring 提供的 BeanUtils.copyProperties() 方法快速实现对象间的属性复制。


🧩 涉及类的字段对比

字段 OrderDetail ShoppingCart 说明
id ✅ 有 ✅ 有 主键,不复制,避免冲突
name ✅ 有 ✅ 有 菜品或套餐名称
dishId ✅ 有 ✅ 有 菜品 ID
setmealId ✅ 有 ✅ 有 套餐 ID
dishFlavor ✅ 有 ✅ 有 菜品口味
number ✅ 有 ✅ 有 数量
amount ✅ 有 ✅ 有 单项金额
image ✅ 有 ✅ 有 菜品图片
orderId ✅ 有 ❌ 无 购物车中不需要订单 ID
userId ❌ 无 ✅ 有 当前登录用户 ID,需手动设置
createTime ❌ 无 ✅ 有 加入购物车时间,需手动设置

🔧 关键代码

List<ShoppingCart> shoppingCartList = orderDetailList.stream().map(x -> {
    ShoppingCart shoppingCart = new ShoppingCart();

    // 拷贝字段:忽略 id(主键),其余字段只要名字相同都会复制
    BeanUtils.copyProperties(x, shoppingCart, "id");

    // 设置当前用户ID(在 OrderDetail 中不存在)
    shoppingCart.setUserId(userId);

    // 设置加入购物车的时间(在 OrderDetail 中不存在)
    shoppingCart.setCreateTime(LocalDateTime.now());

    return shoppingCart;
}).collect(Collectors.toList());

🛠 技术细节分析

1. BeanUtils.copyProperties(source, target, "id")

  • 工具类:org.springframework.beans.BeanUtils
  • 功能:根据字段名和类型相同的匹配原则,将 OrderDetail 中的字段值复制到 ShoppingCart 对象中。
  • 忽略字段:id 不复制,因为两张表的主键不能混用。

2. shoppingCart.setUserId(userId)

  • 购物车是与用户强关联的数据,每一条记录都必须记录是哪个用户添加的。
  • 当前用户 ID 通过 BaseContext.getCurrentId() 获取。

3. shoppingCart.setCreateTime(LocalDateTime.now())

  • 购物车记录通常需要有加入时间以供排序或过期处理。
  • 使用当前时间作为购物车项创建时间。

4. stream().map(...).collect(...)

  • 利用 Java Stream API 进行集合转换。
  • map() 方法逐个处理 OrderDetail 项,将其转化为 ShoppingCart 对象。
  • 最终收集成 List<ShoppingCart> 结果列表。

✅ 总结

步骤 说明
1. 查询订单详情 根据订单 ID 获取 List<OrderDetail>
2. 遍历转换 使用 Stream 和 BeanUtils.copyProperties 进行字段转换
3. 补充字段 手动设置 userIdcreateTime
4. 收集结果 转换后的 ShoppingCart 列表用于后续批量插入数据库

💡 延伸

  • 若需要更灵活地控制字段映射,可以使用 MapStruct 等高级 Bean 映射工具。
  • 使用 BeanUtils 的前提是字段名和类型必须匹配,建议在两个类设计时就考虑字段对齐。
posted @ 2025-05-16 21:26  Nickey103  阅读(31)  评论(0)    收藏  举报