Java Stream API & 对象列表赋值

🧾 技术详解:OrderDetail → ShoppingCart 对象转换
📌 背景说明
在“再来一单”业务场景中,需要将历史订单(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. 补充字段 | 手动设置 userId 和 createTime |
| 4. 收集结果 | 转换后的 ShoppingCart 列表用于后续批量插入数据库 |
💡 延伸
- 若需要更灵活地控制字段映射,可以使用 MapStruct 等高级 Bean 映射工具。
- 使用 BeanUtils 的前提是字段名和类型必须匹配,建议在两个类设计时就考虑字段对齐。

浙公网安备 33010602011771号