【问题标题】:Spring MVC 3.0: How do I bind to a persistent objectSpring MVC 3.0:如何绑定到持久对象
【发布时间】:2011-04-09 23:35:18
【问题描述】:

我正在使用 Spring MVC,我希望它从数据库中绑定一个持久对象,但我无法弄清楚如何设置我的代码以在绑定之前调用数据库。例如,我正在尝试将“BenefitType”对象更新到数据库,但是,我希望它从数据库中获取对象,而不是创建新对象,因此我不必更新所有字段。

    @RequestMapping("/save")
public String save(@ModelAttribute("item") BenefitType benefitType, BindingResult result)
{
    ...check for errors
    ...save, etc.
}

【问题讨论】:

    标签: spring data-binding spring-mvc persistence spring-3


    【解决方案1】:

    虽然您的域模型可能非常简单,以至于您可以将 UI 对象直接绑定到数据模型对象,但很可能并非如此,在这种情况下,我强烈建议您为表单设计一个专门的类绑定,然后在它和控制器中的域对象之间进行转换。

    【讨论】:

      【解决方案2】:

      我有点困惑。我认为您实际上是在谈论更新工作流程?

      你需要两个@RequestMappings,一个用于GET,一个用于POST:

      @RequestMapping(value="/update/{id}", method=RequestMethod.GET)
      public String getSave(ModelMap model, @PathVariable Long id)
      {
          model.putAttribute("item", benefitDao.findById(id));
          return "view";
      }
      

      然后在 POST 上实际更新字段。

      在上面的示例中,您的 @ModelAttribute 应该已经填充了类似上述方法的方法,并且使用 JSTL 或 Spring tabglibs 之类的东西与表单支持对象一起绑定属性。

      您可能还想查看InitBinder,具体取决于您的用例。

      【讨论】:

        【解决方案3】:

        有几种选择:

        • 在最简单的情况下,当您的对象只有简单属性时,您可以将其所有属性绑定到表单字段(hidden,如果需要),并在提交后获得完全绑定的对象。复杂属性也可以使用PropertyEditors 绑定到表单字段。

        • 您也可以使用会话在GETPOST 请求之间存储您的对象。 Spring 3 通过@SessionAttributes 注释(来自Petclinic sample)促进了这种方法:

          @Controller
          @RequestMapping("/owners/*/pets/{petId}/edit")
          @SessionAttributes("pet") // Specify attributes to be stored in the session       
          public class EditPetForm {    
              ...
              @InitBinder
              public void setAllowedFields(WebDataBinder dataBinder) {
                  // Disallow binding of sensitive fields - user can't override 
                  // values from the session
                  dataBinder.setDisallowedFields("id");
              }
              @RequestMapping(method = RequestMethod.GET)
              public String setupForm(@PathVariable("petId") int petId, Model model) {
                  Pet pet = this.clinic.loadPet(petId);
                  model.addAttribute("pet", pet); // Put attribute into session
                  return "pets/form";
              }
              @RequestMapping(method = { RequestMethod.PUT, RequestMethod.POST })
              public String processSubmit(@ModelAttribute("pet") Pet pet, 
                  BindingResult result, SessionStatus status) {
                  new PetValidator().validate(pet, result);
                  if (result.hasErrors()) {
                      return "pets/form";
                  } else {
                      this.clinic.storePet(pet);
                      // Clean the session attribute after successful submit
                      status.setComplete();
                      return "redirect:/owners/" + pet.getOwner().getId();
                  }
              }
          }
          

          但是,如果表单的多个实例在同一个会话中同时打开,这种方法可能会导致问题。

        • 因此,对于复杂情况,最可靠的方法是创建一个单独的对象来存储表单字段,并手动将来自该对象的更改合并到持久对象中。

        【讨论】:

        • 我走上了这条路,但我真的不想使用会话。
        【解决方案4】:

        所以我最终通过在类中使用同名的@ModelAttribute 注释方法来解决这个问题。 Spring 在执行请求映射之前先构建模型:

        @ModelAttribute("item")
        BenefitType getBenefitType(@RequestParam("id") String id) {
            // return benefit type
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-14
          • 2015-12-03
          • 1970-01-01
          • 2016-06-30
          • 1970-01-01
          • 2013-01-17
          • 2014-05-08
          • 1970-01-01
          相关资源
          最近更新 更多