【问题标题】:Binding ManyToMany association with Spring Form将 ManyToMany 关联与 Spring Form 绑定
【发布时间】:2015-03-26 01:58:10
【问题描述】:

我有一个Company 实体,它与一个Acknowledgement 实体有一个ManyToMany 关联。

@Entity
public class Company {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private int id;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "company_acknowledgement", joinColumns = @JoinColumn(name = "company_id"), inverseJoinColumns = @JoinColumn(name = "acknowledgement_id"))
    @OrderBy("name")
    private Set<Acknowledgement> acknowledgements = new HashSet<>();

    ...
}

@Entity
public class Acknowledgement {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private int id;

    @Column(length = 50, nullable = false)
    private String name;

    ...
}

在一个表单中,我希望能够选择一些应该绑定到Company 实体的确认(带有复选框)。因此,当我将带有 POST 的表单提交到我的控制器操作时,我的 Company 对象包含许多 Acknowledgement 对象。

我尝试将 HashSet 更改为 TreeSet as discussed in this question,但没有运气。选中的Acknowledgement 对象将始终存在于我的数据库中,所以基本上我只需要为每个对象填充id 字段。

这是我的控制器代码:

@Controller
public class CompanyController {
    @Autowired
    private CompanyService companyService;

    @RequestMapping("/company/edit/{companyId}")
    public String edit(Model model, @PathVariable int companyId) {
        Company company = this.companyService.get(companyId);
        model.addAttribute("company", company);

        return "company-edit";
    }

    @RequestMapping(value = "/company/edit", method = RequestMethod.POST)
    public String doEdit(Model model, Company company) {
        return ""; // TODO: persist company
    }
}

还有我的 JSP 文件(查看)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<c:url var="actionUrl" value="/company/edit" />

<form:form action="${actionUrl}" commandName="company">
    <form:label path="name">Name:</form:label>
    <form:input path="name" />

    <%-- Other inputs here --%>

    <input type="checkbox" name="acknowledgements[]" value="1" />
    <input type="checkbox" name="acknowledgements[]" value="2" />

    <form:button>Save Changes</form:button>
</form:form>

我尝试了各种方法,以上就是其中之一,但我似乎无法弄清楚如何做到这一点。那么,如何在提交表单时将选定的确认映射到我的Company 实体中的关联?

非常感谢您!

【问题讨论】:

    标签: spring spring-mvc data-binding spring-form


    【解决方案1】:

    您的CompanyAcknowledgement 实体上似乎缺少实现equalshashCode 方法。

    在你的jsp中你只需编写如下代码:

    <form:checkboxes path="acknowledgements" items="${acknowledgementList}" itemValue="id" itemLabel="name"/>
    

    这些家伙有完整的答案: https://stackoverflow.com/a/8718318/3846688

    【讨论】:

      【解决方案2】:

      首先,您需要在控制器中加载完整的确认列表并将其放入您的模型中(比如说确认列表)。简单地加载公司只会加载该公司的确认,而不是完整的列表。

      然后在jsp中:

      <form:checkboxes path="acknowledgements" items="${acknowledgementList}" itemValue="id" itemLabel="name"  />
      

      【讨论】:

        【解决方案3】:

        为什么不编写自定义请求参数解析器? 例如实现接口 HandlerMethodArgumentResolver (更多:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/method/support/HandlerMethodArgumentResolver.html)。

        在“resolverArgument”方法中(基于带有所有参数的请求),您可以使用选定的确认来构建公司实体。

        【讨论】:

          【解决方案4】:

          在你的jsp中,你需要迭代循环如下。

          <c:forEach items="${company.acknowledgements}" var="ack" varStatus="count">
              <input type="checkbox" name="acknowledgements[${count.index}].name" value="${ack.name}" />
           </c:forEach> 
          

          编辑: 你可以试试复选框吗

          <form:checkboxes path="acknowledgements" items="${company.acknowledgements}" />
          

          【讨论】:

          • 这看起来不错,直到我提交绑定对象时出现以下异常的 POST 请求:org.springframework.beans.InvalidPropertyException: Invalid property 'acknowledgements[0]' of bean class [com.example.company.entity.Company]: Cannot get element with index 0 from Set of size 0, accessed using property path 'acknowledgements[0]'
          • 您必须将设置更改为列表以进行确认,因为设置没有索引。此外,Set 的大小似乎为 0。请确保从 companyService.get(companyId); 加载确认。我看到的方法是在实体类中延迟加载的。
          • 很抱歉没有尽快回复您。我将该字段更改为java.util.List 类型(运行时org.hibernate.collection.internal.PersistentBag),但结果相同。该集合确实是通过调用我的服务从数据库中获取的。在点击doEdit控制器动作时发生错误,此时绑定到对象时集合尚未初始化。
          • 我没找到你。你的意思是说这是延迟加载问题?
          • 我的意思是渲染编辑页面时不会出现问题(edit 控制器操作)。在那里,确认加载良好,因为它们已经通过在我的服务中调用 get 方法加载。当 POST 到 doEdit 控制器操作时会出现问题 - 更具体地说是在将 POST 数据绑定到 company 参数时。我不完全确定,但我的猜测是在对象绑定期间,尝试在集合中查找我用复选框选择的索引,但此时集合为空。我希望这会有所帮助。
          猜你喜欢
          • 2017-11-27
          • 1970-01-01
          • 1970-01-01
          • 2018-07-09
          • 2011-12-09
          • 2019-03-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多