2

I have tried and tried but can't figure out what is going on here.

  1. I have a simple controller annotated using @Controller
  2. I also have annotation for @SessionAttributes
  3. I handle a GET request and put an object into the model.
  4. When I get back the POST from the form, I only get back what the user has populated. I'm not getting back the complete object.

I'm new to SessionAttributes but I thought this preserved the whole object and when the object was read back in the method using @ModelAttribute, it would be merged the object (i.e. the object that the form changed). However, I'm not seeing this behavior.

Any help would be much appreciated.

Here is the relevant pieces from the code:

@Controller
@RequestMapping("/user")
@SessionAttributes("user")
public class UserController 
{
      // ... 

@RequestMapping(value = "/{login}", method = RequestMethod.GET)
public String profile(Model model, @PathVariable("login") String login)
      {
           // ...
           model.addAttribute("user", user); 
           // ...
      }

@RequestMapping(value="/{login}", method = RequestMethod.POST)
public String saveProfile(@ModelAttribute("user") @Valid User user, BindingResult result, SessionStatus status)
{
     if (result.hasErrors())
           {
           return "user/index";
     }
           // ... 
           status.setComplete();
     return "redirect:/user/"+user.getLogin(); 
}

Do you see anything that I may have missed? I have spent almost a day trying to figure this out and just can't. Any help would be much appreciated.

Update: I figured out what the issue was. Answer posted below.

4

3 回答 3

3

I figured out what was going after much laboring. I hope this saves somebody else the time.

The underlying problem here was twofold:

  1. The object being saved in the session was decorated with some aspectj notations. Because of this the attribute values for the object were only returned by the appropriate get accessors.
  2. I had hibernate validation in place (note the @Valid annotation in the method that handles the POST). The validator annotations were directly on each field (as below):

    @NotNull private String name;

Here is how I fixed it.

  1. For testing purposes only, I removed the @Valid and noticed that even though the fields themselves seem to be NULL, we were saving the correct data in our backend store. This is what clued me into the root cause of this issue.
  2. I figured the validator annotations were causinI moved the validator notation to get methods. So the code changed as follows:

    private String name;

    @NotNull public String getName() {...}

  3. I put the @Valid annotation back in and verified that the validation was no longer failing.

Hope it helps someone out there and save them a day of work. :)

于 2011-08-23T16:36:01.340 回答
1

我不希望spring合并属性表单会话和表单。您应该将表单提交的用户和会话中的用户分开。

于 2011-08-23T09:50:42.317 回答
1

我和 Azeem 有同样的问题,并且由于他没有明确确认 sessionattribute 可用于将原始表单支持对象与提交中发布的更改“合并”,我想指出是的,表单的更改提交确实被合并到原始表单支持对象中。

如中所指出的,这种方法可能存在一些问题

Spring MVC 3.0:如何绑定到持久对象

但是当您有一个复杂的表单支持对象但您只允许用户更新表单中的一些对象图成员而不使用隐藏字段来维护表单元素中复杂对象的其余部分时,这种方法非常有用。

当在类上不使用@SessionAttributes("xxx") 注释而使用这种方法时,返回的表单支持对象基本上是空的,除了那些由表单专门提交的成员。这会使更新对象的持久化变得非常困难,因为您必须自己将新更新合并到原始对象中。但是通过使用 session 属性,提交后提供的完整更新的表单支持对象使得持久化对象图变得更加容易。

于 2013-10-21T07:26:29.607 回答