在Spring MVC中从Set绑定到<form:select> </form:select>

时间:2012-10-26 09:49:14

标签: java spring spring-mvc

我正在使用Spring MVC创建Web,我仍然是Spring的初学者。我有两个实体,有很多关系。在实践中,我有UserGroup,它可以有多个或一个(或没有)UserAuthority我想使用具有多个select的表单来编辑这些关系。创建新的UserGroup实体或编辑现有的实体工作正常,只有一个小问题:编辑现有的UserGroup时,没有在选择框中选择适当的权限。我已经在这方面工作了一天多没有成功。有人可以帮助我吗?

我的实体模型是:

@Entity
public class UserGroup {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
        name = "user_group_has_user_authority",
        joinColumns = {
            @JoinColumn(name = "user_group_id")},
        inverseJoinColumns = {
            @JoinColumn(name = "user_authority_id")})
    private Set<UserAuthority> authorities;
}

(我遗漏了getter和setter,但我的代码中有它们)

public class UserAuthority {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;

    private String code;

    private String name;
}

(再一次,我遗漏了二传手和吸气鬼)。

我的表单如下:

<form:form action="${action}" method="post" commandName="userGroup" id="user-group-form">
    <form:input readonly="true" cssClass="dn" path="id"/>
    <table>
        <tr>
            <td>
                <form:label path="title">Title</form:label>
                <form:errors path="title" />
            </td>
            <td>
                <form:input path="title"/>
            </td>
        </tr>
        <tr>
            <td>
                <form:label path="authorities">Authorities</form:label>
                <form:errors path="authorities" />    
            </td>
            <td>
                <form:select path="authorities" multiple="true" items="${authoritiesList}" />
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Save" />
            </td>
        </tr>
    </table>
</form:form>

我的控制器方法如下:

@RequestMapping(value = "/editGroup", method = RequestMethod.GET) 
public ModelAndView editGroup(Model model, HttpServletRequest request) {
    Long id = null;
    UserGroup userGroup = null;
    HashMap<String, Object> editModel = new HashMap<>(2);

    try {
        id = Long.parseLong(request.getParameter("id"));
    } catch (NumberFormatException ex) {
    }
    if (id != null) {
        userGroup = groupsManager.get(id);
    } 

    UserGroupData userGroupData = groupsManager.createFromUserGroup(userGroup);

    editModel.put("userGroup", userGroupData);
    editModel.put("authoritiesList", getAuthoritiesList());

    return new ModelAndView("/users/groupEdit", editModel);
}

@RequestMapping(value = "/editGroup", method = RequestMethod.POST)
public String updateGroupAction(@ModelAttribute("userGroup") @Validated UserGroupData userGroupData, BindingResult result, Model model, HttpServletRequest request) {

    if (result.hasErrors()) {
        model.addAttribute("userGroup", userGroupData);
        return "/users/groupEdit";
    }
    groupsManager.saveUserGroupData(userGroupData);
    return "redirect:/users/listGroup";
}

private Map <Long, String> getAuthoritiesList() {      //I also tried returning Map<String,String> but result was same.
    Map<Long,String> authorities = new LinkedHashMap<>();
    for (UserAuthority ua : authorityManager.getAll()) {
        authorities.put(ua.getId(), ua.getName());
    }
    return authorities;
}

Finnaly,我使​​用这个转换器从String创建UserAuthority(实际上我在某处搜索了这个,但它有效:))     public class StringToUserAuthorityConverter实现Converter {

    /**
     * The string that represents null.
     */
    private static final String NULL_REPRESENTATION = "null";

    @Autowired
    private UserAuthorityDao authorityDao;

    @Override
    public UserAuthority convert(final String id) {
        if (id.equals(NULL_REPRESENTATION)) {
            return null;
        }
        Long lId = null;
        try {
            lId = new Long(id);
        } catch (NumberFormatException e) {

        }
        return authorityDao.find(lId);
    }
}

正如我所说,所有创建和编辑工作,只有我遇到的问题是,在编辑现有组时,未选择已与组关联的权限。任何帮助将不胜感激。

修改

我发现了两件事,也许它会有所帮助:

1)在html页面中,有以下字段:

<input type="hidden" value="1" name="_authorities">

我读过它应该包含我的权限字段表单模型的值,但无论如何,它在我的情况下总是包含1

2)如果我的表单未通过验证(这意味着如果我没有输入Title,这是强制性的)表单重新加载并显示错误消息,但是选择框为空。不是它的标志吗?

编辑2

我从上次编辑中解决了第2点...

3 个答案:

答案 0 :(得分:2)

您需要在equals()实体类中实施hashCode()Authority方法。这是因为Set(和其他集合)检查对象是否相等,这就是Spring标记已选择字段的方式。

http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html/persistent-classes.html#persistent-classes-equalshashcode

答案 1 :(得分:1)

所以我做了一个丑陋的解决方案。虽然它有效,但代码并不像我希望的那样好。我在jsp中编辑了我的表单,如下所示:

<form:select path="authorities" multiple="true" >
     <c:forEach var="authority" items="${authoritiesList}">
         <c:choose>
             <c:when test="${userGroup.authorities.contains(authority) eq true}">
                 <option value="${authority.id}" selected="selected">${authority.name}</option>
             </c:when>
             <c:otherwise>
                 <option value="${authority.id}">${authority.name}</option>
             </c:otherwise>
        </c:choose>
    </c:forEach>
</form:select>

但必须有更好的方法......

答案 2 :(得分:0)

您应该使用AutoPopulatingList进行转换,此功能在Spring中可用于将列表数据转换为模型列表。 example