Spring Boot JPA@Transactional@Service不会更新,但控制器中的@Transaction



我有一个非常基本的Spring Boot/JPA堆栈应用程序,它有一个控制器、服务层和存储库,但我认为它不会持久更新。

一个琐碎的实体:

@Entity
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
protected Customer() {}
public Customer(String name) { this.name = name; }
// standard getters,setters //
}

一个琐碎的存储库:

@Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {}

一个简单的服务层:

// If the service is @Transactional and the controller is not, the update does NOT occur
@Transactional
@Service
public class CustomerService {
private static final Logger LOG = getLogger(CustomerService.class);
@Autowired
private CustomerRepository customerRepository;
boolean updateCustomerName(Long id, String name) {
Customer customer = customerRepository.findOne(id);
if (customer == null) { return false; }
// Modifies the entity
customer.setName(name);
// No explicit save()
return true;
}
}

以及一个使用所有功能的REST控制器:

// If the controller is @Transactional and the service is not, the update occurs
@RestController
@RequestMapping("/mvc")
public class CustomerController {
@Autowired
private CustomerService customerService;
@RequestMapping(path = "{id}", method = RequestMethod.PUT)
public ResponseEntity updateCustomerName(@PathVariable Long id, @RequestParam("name") String name) {
customerService.updateCustomerName(id,name);
return ResponseEntity.noContent().build();
}
}

它们通过一个简单的单线SpringBootApplication连接在一起

我启用了SQL调试日志,并查看了选择、更新等

使用上面的代码:当控制器调用服务方法时,修改后的实体是而不是持久化的。SQL日志显示实体的select,但没有显示update

如果没有任何内容标记为@Transactional,则也没有更新

但是,只需将@Transactional注释从服务类移动到控制器类,SQLupdate就会发生

如果我向服务方法添加一个显式的customerRepository.save(customer),那么更新也会发生。但我的理解是ORM应该自动保存修改后的持久实体。

我确信这个问题与web请求中的EntityManager生命周期有关,但我感到困惑。我需要做额外的配置吗?

完整示例位于https://github.com/monztech/SO-41515160

编辑:此问题已解决,请参阅下文。根据Spring规范,@Transactional在包私有方法中不起作用,并且错误地没有公开更新服务方法。

如果方法是public并且服务类具有@Transactional注释,则会发生更新。

不过,我还有一个问题。为什么@Transactional注释是必要的?(如果没有它,更新就不会发生)实体管理器不应该因为Spring使用的视图中的打开会话机制而独立于任何事务而仍然保留对象吗?

updateCustomerName方法公开。

最新更新