@Transactional //一个业务中包含多个增删改操作,所以要添加事务 @Override public void delete(List<Long> ids) { for (Long id : ids) { Dish dish = dishMapper.getById(id); if (dish.getStatus() == StatusConstant.ENABLE) { //判断如果菜品在起售中,那么就不能删除 throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE); } } //删除菜表中的数据 List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids); if (setmealIds != null && setmealIds.size() > 0) { //当前菜品被套餐关联了,不能删除 throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL); } for (Long id : ids) { dishMapper.deleteById(id);//后绪步骤实现 //删除菜品关联的口味数据 dishFlavorMapper.deleteByDishId(id);//后绪步骤实现 } }
时间: 2023-12-06 19:41:34 浏览: 48
这代码是一个菜品删除的业务逻辑,使用了事务注解 @Transactional 来保证多个操作的原子性。首先,它遍历了传入的菜品 id 列表,检查每个菜品是否处于起售状态,如果是则抛出 DeletionNotAllowedException 异常,表示不允许删除。接着,它查询该菜品是否被任何套餐关联,如果是则同样抛出 DeletionNotAllowedException 异常。最后,它遍历菜品 id 列表,依次删除菜品信息和与该菜品关联的口味数据。
相关问题
一方法调用多数据源方法需要在同一个事务中,怎么配置 @Transactional
如果一个方法需要调用多个使用不同数据源的方法,并且这些方法需要在同一个事务中执行,可以使用 `@Transactional` 注解来实现。
在使用 `@Transactional` 注解时,需要指定要使用的事务管理器的名称。可以通过在方法上使用 `@Transactional` 注解,并指定要使用的事务管理器的名称,来实现在同一个事务中执行多个使用不同数据源的方法。
例如,假设有两个方法,分别位于不同的服务中,需要在同一个事务中执行:
```java
@Service
public class ServiceA {
@Autowired
private ServiceB serviceB;
@Autowired
@Qualifier("primaryTransactionManager")
private PlatformTransactionManager primaryTransactionManager;
@Autowired
@Qualifier("secondaryTransactionManager")
private PlatformTransactionManager secondaryTransactionManager;
@Transactional(value = "chainedTransactionManager") // 事务注解,指定使用链式事务管理器
public void doSomethingInBothDataSources() {
// 在第一个数据源上执行一些操作
// ...
// 在第二个数据源上执行一些操作
serviceB.doSomethingInSecondaryDataSource();
// 在第一个数据源上继续执行一些操作
// ...
}
@Transactional(value = "primaryTransactionManager") // 事务注解,指定使用第一个数据源的事务管理器
public void doSomethingInPrimaryDataSource() {
// 在第一个数据源上执行一些操作
// ...
}
}
```
在上面的示例中,`ServiceA` 类中定义了两个方法,其中一个需要在两个不同的数据源上执行一些操作。使用 `@Transactional` 注解时,通过指定事务管理器的名称来决定使用哪个数据源的事务管理器。在这个例子中,使用了一个名为 `chainedTransactionManager` 的链式事务管理器,该管理器将两个数据源的事务管理器连接在一起,以实现在同一个事务中执行多个使用不同数据源的方法。
需要注意的是,在同一个事务中执行多个不同数据源的方法时,需要确保这些方法都在同一个线程中执行。如果这些方法在不同的线程中执行,则无法在同一个事务中执行。
举例说明如果在同一个类中调用被 @Transactional 注解修饰的方法,事务将不会生效。
假设我们有一个 UserService 类,其中有两个方法 addUser 和 deleteUser,它们都被 @Transactional 注解修饰:
```
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void addUser(User user) {
userRepository.save(user);
}
@Transactional
public void deleteUser(Long userId) {
userRepository.deleteById(userId);
// 抛出异常来模拟事务回滚
throw new RuntimeException("deleteUser failed");
}
}
```
现在我们在 addUser 方法中调用 deleteUser 方法:
```
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void addUser(User user) {
userRepository.save(user);
deleteUser(user.getId());
}
@Transactional
public void deleteUser(Long userId) {
userRepository.deleteById(userId);
// 抛出异常来模拟事务回滚
throw new RuntimeException("deleteUser failed");
}
}
```
然后我们在业务逻辑中调用 addUser 方法:
```
@Service
public class BusinessService {
@Autowired
private UserService userService;
@Transactional
public void addUser(User user) {
userService.addUser(user);
}
}
```
我们期望的是,当 addUser 方法执行失败时,整个事务能够回滚。但是实际上,当 addUser 方法调用 deleteUser 方法时,deleteUser 方法的事务不会生效,因为它们都在同一个类中。这意味着,当 deleteUser 方法抛出异常时,addUser 方法中保存的 user 记录不会被回滚,而 deleteUser 方法中删除的 userId 记录也不会被回滚,导致数据不一致。
因此,如果在同一个类中调用被 @Transactional 注解修饰的方法,事务将不会生效。为了避免这种情况,我们应该将这些方法放在不同的类中,或者在同一个类中使用 AOP 来确保事务生效。