【问题标题】:In Spring 3.2, does RedirectAttributes really pass the attributes themselves? Losing elements在 Spring 3.2 中,RedirectAttributes 真的会自己传递属性吗?丢失元素
【发布时间】:2013-10-02 15:41:06
【问题描述】:

注意:最终我的目标只是将生成的 URL 从“/public/academy/register?param=blah”更改为自定义的 SEO 化 URL,如代码所示。如果我通过尝试从在 POST 映射中返回“成功视图”JSP 更改为使用 post-redirect-get(无论如何这是一个很好的做法)而走错了路,我愿意接受建议。

以下是两种方法:获取注册表单并进行处理的 POST 请求映射,以及成功页面的映射方法。我正在为重定向添加一个 flash 属性,该属性包含 POST 到第一个方法的表单。

表单具有Form -> Schedule -> Course -> Content -> Vendors 的属性层次结构,其中每个都是它自己的类对象,除了Vendors 是SortedSet<Vendor>。当我加载成功页面时,我收到一个 Hibernate 异常,指出无法延迟初始化供应商。为什么它在链条的下游如此之远以至于它停止加载,或者更基本上,为什么它首先失去了这个属性值?当我在返回之前设置断点时,RedirectAttributes 对象以我传递给它的表单填充了供应商。什么给了?

@RequestMapping(value = "/public/academy/register", method = RequestMethod.POST)
public String processSubmit(Site site, Section section, User user,
        @ModelAttribute @Valid AcademyRegistrationForm form,
        BindingResult result, Model model, RedirectAttributes redirectAttributes) {
    validator.validate(form, result);

    if (site.isUseStates()
            && StringUtils.isBlank(form.getBooker().getState())) {
        result.rejectValue("booker.state",
                "gui.page.academy.attendee.state");
    }

    if (result.hasErrors()) {
        LOG.debug("Form has errors: {}", result.getAllErrors());
        return "common/academy-registration";
    }

    // Form is valid when no errors are present. Complete the registration.
    AcademyRegistration registration = form.toAcademyRegistration();
    academyService.performRegistration(registration, site);

    redirectAttributes.addFlashAttribute(form);

    String redirectUrl = "redirect:/public/academy/register/"
        + registration.getSchedule().getCourse().getContent().getSeoNavTitle() 
        + "-completed";

    return redirectUrl;
}

@RequestMapping(value="/public/academy/register/**-completed", method=RequestMethod.GET)
public String displayRegistrationSuccess(@ModelAttribute("academyRegistrationForm") final AcademyRegistrationForm form)
{
    SortedSet<Vendor> dummy = form.getSchedule().getCourse().getContent().getVendors();
    return "common/academy-registration-success";
}

这是一个例外:

Oct 2, 2013 2:11:31 PM org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet jsp threw exception
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.horn.cms.domain.Content.vendors, could not initialize proxy - no Session

【问题讨论】:

  • 请发布休眠异常。
  • 完成了 Sotirios,感谢您的提醒。

标签: spring hibernate spring-mvc post-redirect-get


【解决方案1】:

这是我假设发生的情况(直到您更新详细信息):

AcademyRegistration registration = form.toAcademyRegistration();
academyService.performRegistration(registration, site);

做一些 Hibernate 查询并延迟检索一些持久化实体,即。他们还没有被初始化。确实发生的加载可能发生在某些 Hibernate Session 中(你在某处有 @Transactional 吗?)。 Session 已关闭并与延迟加载的对象解除关联。

然后将form 对象添加到RedirectAttributes,该对象对延迟加载的实体(它将是一个休眠代理)有一些嵌套引用。这本身不是问题,因为您所做的只是传递一个引用。

请求处理通过发送 302 响应完成。然后,您的客户将发出由displayRegistrationSuccess() 处理的新请求并点击此行

SortedSet<Vendor> dummy = form.getSchedule().getCourse().getContent().getVendors();

这里,form 对象与上一个请求中添加的对象相同。此引用链中的对象之一是您的 Hibernate 代理,它被延迟初始化。因为该对象不再与 Session 关联,所以 Hibernate 会抱怨并且您会得到异常。

传递(跨越请求边界)依赖于持久状态的对象不是一个好主意。相反,您应该传递一个用于检索实体的 ID。另一种方法是在您的 academyService 方法中完全初始化您的对象。

【讨论】:

  • 很有意义。我开始在供应商上使用 Hibernate.initialize(),然后不得不继续进行一长串的属性初始化,直到我决定,你是对的,进行一次额外的数据库调用以从数据库中检索 AcademyRegistration 信息是值得的不必深入挖掘对象层次结构。从 displayRegistrationSuccess 方法中检索实体并像魅力一样工作。谢谢!
  • @Eric 不客气。也可以考虑使用FetchType.EAGER
猜你喜欢
  • 2011-10-02
  • 1970-01-01
  • 2020-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-07
相关资源
最近更新 更多