【发布时间】:2018-08-15 05:31:24
【问题描述】:
我有一个控制器,我正在通过验证器验证 ModelAttribute,然后像下面的代码一样更新实体。验证器在 obj 变量中接收要更新的对象。
我遇到的问题是,当我运行这个方法 restaurantRepository.findByEmail 时,验证方法中的修改对象(obj)被保存到数据库中。它与@Transactional 有关。我不明白为什么它会保存 obj,我还没有将它传递给方法。
我已阅读此 SO 帖子 Why does @Transactional save automatically to database 答案是这样的
在事务方法即将返回之前,事务提交,这意味着对托管实体的所有更改都会刷新到数据库中。
但我知道托管实体是存在于@Transactional 范围内的实体。我没有将 obj 传递给方法,所以我不明白为什么它会自动保存。
餐厅
@Entity
@Table(name="restaurant")
@SequenceGenerator(name="restaurant_seq", sequenceName="restaurant_seq")
public class Restaurant{
private String name;
private String email;
private String phonenumber;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhonenumber() {
return phonenumber;
}
public void setPhonenumber(String phonenumber) {
this.phonenumber = phonenumber;
}
}
餐厅管理员
@RequestMapping("/restaurant")
@Controller
public class RestaurantController {
@Autowired
private RestaurantService restaurantRepository;
@Autowired
private RestaurantValidator restaurantValidator;
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(restaurantValidator);
}
@GetMapping("/{id}")
public String viewRestaurant(@PathVariable("id") Long restaurant_id, final ModelMap model) {
Restaurant restaurant = restaurantService.findById(restaurant_id);
if(!model.containsAttribute("restaurantModel")){
model.addAttribute("restaurantModel", restaurant );
}
return "pages/restaurant_view_new";
}
@PatchMapping("/{restaurantModel}")
public String updateRestaurant(@Valid @ModelAttribute("restaurantModel") Restaurant editRestaurant, BindingResult bindingResult, final ModelMap model, RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.restaurantModel", bindingResult);
redirectAttributes.addFlashAttribute("restaurantModel", editRestaurant);
redirectAttributes.addFlashAttribute("saveErrors", true);
return "redirect:/restaurant/" + editRestaurant.getId();
}
restaurantRepository.save(editRestaurant);
redirectAttributes.addFlashAttribute("saveSuccess", true);
return "redirect:/restaurant/" + editRestaurant.getId();
}
}
餐厅验证器
@Component
public class RestaurantValidator implements Validator {
@Autowired
RestaurantRepository restaurantRepository;
public boolean supports(Class clazz) {
return Restaurant.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
ValidationUtils.rejectIfEmpty(e, "name", "form.required");
ValidationUtils.rejectIfEmpty(e, "email", "form.required");
ValidationUtils.rejectIfEmpty(e, "phonenumber", "form.required");
Restaurant p = (Restaurant) obj;
if(restaurantRepository.findByEmail(p.getEmail()).size() > 0 ){
e.rejectValue("email", "form.email.duplicate");
}
}
}
RestaurantRepository
@Transactional
public interface RestaurantRepository extends JpaRepository<Restaurant, Long>{
List<Restaurant> findByEmail(String email);
}
【问题讨论】:
-
我在您发布的内容中没有看到任何修改 obj 的代码。
-
抱歉。在控制器的 POST 请求中收到时,obj 已被修改。修改成html表单提交给控制器。
-
代码很重要。发布它。
-
@JBNizet 我已经添加了控制器代码。当它到达 PatchMapping 方法的第一行时,对象已经被保存。我可以验证这一点,因为我可以看到在休眠日志上运行“UPDATE”语句。
-
请贴出实体的代码
标签: java spring hibernate jpa transactional