Spring @Transactional 只有在调用者也是@Transactional 时才有效

Spring @Transactional only works if caller is also @Transactional

我很难理解为什么当我尝试使用 @Scheduled 方法时我的更新没有提交。
这是我的场景的简化:

@Service
public class UserService {

    @Transactional
    public void updateUser(User user){
        user.setName("Doe");
    }
}

从两个位置调用此服务:

@RestController
@RequestMapping(value = "/users")
public class UserController {

    @Autowired
    private UserService  userService;
    @Autowired
    private UserRepository userRepository;

    @ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public void getAvailableIssuers(@PathVariable("id") String id){
        User user = userRepository.findOne(id);
        userService.updateUser(user);
    }
}

和使用 @Scheduled 方法的服务:

@Component
class InternalService {

    @Autowired
    private UserService  userService;

    @Autowired
    private UserRepository userRepository;

    @Scheduled(fixedRate=1000)
    public void updateUser(){
        User user = userRepository.findOne(1L);
        userService.updateUser(user);
    }
}

我的问题是,当我尝试通过 InternalService 更新用户时,用户永远不会更新 - 但它通过 RestController 更新得非常好。当我为预定方法添加 @Transactional 注释时(即使使用 readOnly = true),它也有效。

我阅读了 spring 中有关交易的文档,但我仍然不明白为什么它不起作用。我检查了调试器,userService 的形式是 Spring 代理。

谁能帮我解释一下?

问题是您的操作不限于该服务方法:在这两种情况下,您都是在调用方法中从存储库中检索对象。您的事务必须涵盖整个数据库操作集合。

至于为什么您的控制器实际上 工作,仅凭这些信息我不能确定,但​​我猜您正在使用 OpenEntityManagerInView并免费获得交易边界。