源代码
/**
* 菜品停售起售
*/
@Transactional
public void statusChange(Integer status, Long id) {
Dish dish = Dish.builder()
.id(id)
.status(status)
.build();
dishMapper.update(dish);
if(status == StatusConstant.DISABLE){
List<Long> dishIds = new ArrayList<>();
dishIds.add(id);
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(dishIds);
if(setmealIds != null && setmealIds.size()>0){
for(Long setmealId :setmealIds){
Setmeal setmeal = Setmeal.builder()
.id(setmealId)
.status(StatusConstant.DISABLE)
.build();
setmealMapper.update(setmeal);
}
}
}
}
解释
/**
* 使用 @Transactional 注解标记这个方法应该在一个事务中执行,以确保所有的数据库操作要么全部成功提交,要么全部失败回滚。
*/
@Transactional
public void statusChange(Integer status, Long id) {
/**
* 方法的签名,指定了方法的访问修饰符、返回类型和参数。这个方法接受两个参数:`status` 表示菜品的状态(停售或起售),`id` 表示要操作的菜品的ID。
*/
Dish dish = Dish.builder()
.id(id)
.status(status)
.build();
/**
* 调用 `dishMapper` 的 `update` 方法,将新创建的 `Dish` 对象传递给它,以更新菜品的状态。
*/
dishMapper.update(dish);
/**
* 检查菜品的状态是否是停售状态。`StatusConstant.DISABLE` 是一个常量,表示停售状态。
*/
if(status == StatusConstant.DISABLE){
/**
* 如果菜品状态是停售,这段代码将查询与该菜品关联的套餐的ID列表。首先,创建了一个包含当前菜品ID的列表,
* 然后调用 `setmealDishMapper` 的方法来获取与这些菜品ID关联的套餐ID列表。
*/
List<Long> dishIds = new ArrayList<>();
dishIds.add(id);
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(dishIds);
/**
* 如果存在关联的套餐,并且菜品状态是停售,这段代码将遍历这些套餐,并逐个将它们的状态更新为停售。它创建了一个 `Setmeal` 对象,
* 设置了套餐ID和停售状态,然后通过 `setmealMapper` 来更新套餐状态。
*/
for(Long setmealId : setmealIds){
Setmeal setmeal = Setmeal.builder()
.id(setmealId)
.status(StatusConstant.DISABLE)
.build();
setmealMapper.update(setmeal);
}
}
}
q:为什么不能直接修改对象中status的值而要创建一个新的对象更新
a:在Java中,对象是引用类型,传递对象是传递引用的副本。因此,如果直接修改传入的对象的属性,会影响到原始对象。这可能会导致意外的副作用,特别是在多线程环境下或者在需要记录对象变更历史的情况下。
因此,为了保证代码的可维护性和可预测性,通常会创建一个新的对象,并将其用于修改操作。这样做的好处有:
-
不影响原始对象:通过创建一个新的对象,可以保持原始对象的状态不变,不会因为修改操作而受到影响。
-
可追踪性:通过创建一个新的对象,可以清晰地记录修改操作的内容,便于后续的调试和维护。
-
线程安全性:在多线程环境下,直接修改对象可能会引发并发问题。通过创建一个新的对象,可以避免并发修改导致的不一致性。
-
更清晰的逻辑:通过创建一个新的对象,可以清晰地表达修改操作的意图,提高代码的可读性和可理解性。
因此,虽然直接修改对象属性也是可以实现的,但为了保证代码的稳健性和可维护性,通常建议创建一个新的对象,并将其用于修改操作。