【问题标题】:@ModelAttribute having Collection property - values get added to the collection, not replaced?@ModelAttribute 具有 Collection 属性 - 值被添加到集合中,而不是被替换?
【发布时间】:2013-02-12 10:54:13
【问题描述】:

我有这门课:

PreApprovalRequest 类有一个属性headings,它会自动填充到控制器中(参见页面下方的控制器代码)。

public class PreApprovalRequest {
    private Long id;
    private String Description;
    private Collection<Headings> headings; //this property!
}

还有控制器:

@Controller
@SessionAttributes({"preApprovalRequest", "productRecommendations"})
public class RequestController {

    @RequestMapping(value = "/submit",  method = RequestMethod.POST)
    public String submitResults(@ModelAttribute(value = "preApprovalRequest") @Valid PreApprovalRequest preApprovalRequest, BindingResult errors) {
        //HERE: It looks like if I have some headings in the preApprovalRequest object already, the call of this method will not delete those, but will append to the existing list.
        //save object in DB.
        return "dashboard";
    }
}

知道如何让 Spring 替换集合对象而不是添加到它吗?

【问题讨论】:

  • 这是 SessionAttributes 持有相同 preApprovalRequest 变量的预期行为。如果您不希望从您提交的内容中创建新的headings,只需将其从SessionAttributes 中删除
  • 我每次都想要一个新的标题。这就是问题所在,我不明白。 Spring 似乎只是添加到标题列表中,而不是删除旧的并只保留新的。我不知道为什么有人甚至想要那个,不明白他们为什么在 Spring 中这样实现它?!

标签: java spring session spring-mvc


【解决方案1】:

我对您的问题的理解是,您不能替换您的headings 收藏以拥有Headings 的新收藏。你不能通过以下方式做到这一点吗?

preApprovalRequest.setHeadings(new ArrayList<Headings>());
preApprovalRequest.getHeadings().add(heading1);

【讨论】:

  • 是的,您理解正确。我希望 Spring 删除旧列表并将新列表放入对象中。不,这是行不通的,因为标题的设置是由 Spring 自动完成的,所以当我开始按照您的建议进行操作时,Spring 已经将新标题添加到旧列表中。因此我不知道哪些是新标题,哪些是旧标题...
【解决方案2】:

即使这是您第一次提交表单,也会发生这种情况吗?如果没有,请在您完成控制器中的所有操作后尝试清理缓存。

在您的方法中添加 SessionStatus 并调用“setComplete()”来清理属性。因此,您第二次启动流程时,您的缓存将是空的,您将不得不使用新的 preApprovalRequest

@RequestMapping(value = "/submit",  method = RequestMethod.POST)
public String submitResults(@ModelAttribute(value = "preApprovalRequest") @Valid PreApprovalRequest preApprovalRequest, BindingResult errors, SessionStatus status) {
    /HERE: It looks like if I have some headings in the preApprovalRequest object already, the call of this method will not delete those, but will append to the existing list.
    //save object in DB.

    status.setComplete();
    return "dashboard";
}

【讨论】:

  • 是的,它一直在发生。我无法完成会话,因为当我设置标题时,“向导”尚未完成。一旦 PreApprovalRequest 保存在 DB 中,我就会这样做,稍后会执行一个向导步骤。
【解决方案3】:

如果您正在寻找的是动态收缩/扩展类型的列表,那么集合必须是惰性的。Apache commons 集合提供了一个惰性列表类来执行此操作。您可以从以下位置获取 apache commons 集合:http://commons.apache.org/collections/

所以你的控制器模型可以重写为:

public class PreApprovalRequest {
    private Long id;
    private String Description;
    private List headings;

    public PreApprovalRequest()
    {
        headings=LazyList.decorate(
           new ArrayList(),
           FactoryUtils.instantiateFactory(Header.class));
    }

}

将数据绑定到列表背后的想法是,在 html 元素名称属性中跟踪列表项索引:

<c:forEach item="${modelAttr.list}" varStatus="listItem">

<form:input type="text" path="list[${listItem.index}]" />

</c:forEach>

【讨论】:

  • 谢谢,但不,这不是我要找的。我只希望 Spring 不要将新标题添加到会话对象中已有的列表中,而是用新提交的标题替换旧标题。
猜你喜欢
  • 1970-01-01
  • 2013-08-20
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 2015-09-05
  • 2019-05-22
  • 1970-01-01
  • 2016-06-02
相关资源
最近更新 更多