文档章节

SpringMVC Checkbox 对List<object> 数据绑定

Vincent-Duan
 Vincent-Duan
发布于 2015/06/08 12:11
字数 721
阅读 1897
收藏 4

http://stackoverflow.com/questions/8700339/spring-mvc-usage-of-formcheckbox-to-bind-data

I know there have been already questions around this topic, but I have not figured out how to solve the following issue:

I have a user/roles relationship and I want to list all available roles in a JSP as checkbox items, where the users assigned checkboxes are selected. However, the matching items are not checked (here I am using Spring 3.1).

Extract from the User object:

private Set<RoleEntity> roles = new HashSet<RoleEntity>();

Extract from the Spring Controller (adding user object and role list to Model):

UserEntity userEntity = userEntityService.findById(UserEntity.class, new Long(id));model.addAttribute("userAttribute", userEntity);List<RoleEntity> roleList = roleEntityService.findAll();model.addAttribute("roleList", roleList);

Extract from the JSP:

<form:form modelAttribute="userAttribute" method="POST" action="${saveUrl}">...    <table align="center">
        <tr>
            <td>ID</td>
            <td>Role Name</td>
        </tr>
        <c:forEach items="${roleList}" var="role" varStatus="status">
            <tr>
                <td><form:checkbox path="roles" value="${role}" label="${role.id}" /></td>
                <td><c:out value="${role.name}" /></td>
            </tr>
        </c:forEach>
    </table>...</form:form>

The Spring MVC documentation says this: When the bound value is of type array or java.util.Collection, the input(checkbox) is marked as 'checked' if the configured setValue(Object) value is present in the bound Collection.

Isn't that the case here? What am I missing here?

My guess is you are missing the implementation for the equals and hashcode methods on the RoleEntity class.

When the bound value is of type array or java.util.Collection, the input(checkbox) is marked as 'checked' if the configured setValue(Object) value is present in the bound Collection.

This is correct, but to check for presence in a HashSet you need equals and hashcodeimplemented correctly.

Just as a quick test to see if that's the problem, replace this line:

model.addAttribute("roleList", roleList);

with this line:

model.addAttribute("roleList", userEntity.getRoles());

Do you get all your checkboxes checked? If yes, then you didn't provide your own equals and hashcode and the default ones are used (those inherited from Object).

The default equals compares identity which means that a variable holds the same instance as another variable. Equality means two different object contain the same state or have the same meaning, so to speak.

Using model.addAttribute("roleList", userEntity.getRoles()) triggers the default equalsmethod to return true because the list and values you check for presence in the list are identical (two identical objects are always equal).

But in your case you use userEntityService.findById for one and roleEntityService.findAll for the other which means different objects. At this point you have to use a proper equality test as opposed to identity.

Do you have equals/hashcode implemented?

Based on your code, here is an example that works:

Controller:

import java.util.Arrays;import java.util.Collections;import java.util.HashSet;import java.util.List;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;@Controllerpublic class SomeController {
    @RequestMapping(value = "/something", method = { RequestMethod.GET, RequestMethod.POST })
    public String handle(Model model) {

        UserEntity userEntity = new UserEntity();
        userEntity.setRoles(new HashSet<RoleEntity>());
        Collections.addAll(userEntity.getRoles(), 
                                new RoleEntity(1, "one"), 
                                new RoleEntity(3, "three"));
        model.addAttribute("userAttribute", userEntity);        

        List<RoleEntity> roleList = Arrays.asList(
                                        new RoleEntity(1, "one"), 
                                        new RoleEntity(2, "two"), 
                                        new RoleEntity(3, "three")
                                    );
        model.addAttribute("roleList", roleList);

        return "view";
    }}

User class:

import java.util.HashSet;import java.util.Set;public class UserEntity {
    private Set<RoleEntity> roles = new HashSet<RoleEntity>();

    public Set<RoleEntity> getRoles() {
        return roles;
    }
    public void setRoles(Set<RoleEntity> roles) {
        this.roles = roles;
    }}

Roles class (notice the equals and hashcode methods; if you remove them, the example no longer works):

public class RoleEntity {
    private long id;
    private String name;

    @Override
    public int hashCode() {
        return new Long(id).hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (! (obj instanceof RoleEntity)) {
            return false;
        }
        return this.id == ((RoleEntity)obj).getId();
    }

    public RoleEntity(long id, String name) {
        this.id = id;
        this.name = name;
    }

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }}

View:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%><%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %><%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><form:form modelAttribute="userAttribute" method="POST" action="/something">
    <table align="center">
        <tr>
            <td>ID</td>
            <td>Role Name</td>
        </tr>
        <c:forEach items="${roleList}" var="role">
            <tr>
                <td><form:checkbox path="roles" value="${role}" label="${role.id}" /></td>
                <td><c:out value="${role.name}" /></td>
            </tr>
        </c:forEach>
    </table></form:form>


© 著作权归作者所有

共有 人打赏支持
Vincent-Duan

Vincent-Duan

粉丝 9
博文 303
码字总数 99988
作品 0
海淀
5:spring mvc 数据类型转换

SpringMVC如何实现数据类型转换 1、类型转换:首先表单数据(全部是字符串)通过WebDataBinder进行绑定到命令对象,内部通过Converter SPI实现; 2、数据验证:使用JSR-303验证框架进行验证;...

小杰java
2017/10/18
0
0
HibernateCallback

HibernateTemplate还提供一种更加灵活的方式来操作数据库,通过这种方式可以完全使用Hibernate的操作方式。HibernateTemplate的灵活访问方式是通过如下两个方法完成: q Object execute(Hib...

疯狂的艺术家
2011/06/12
0
0
ListView设置点击效果

我们先看一下一个 ListView绑定6行数据,每行数据上包括了三个控件:TextView,CheckBox,Button,运行效果如下图所示: 绑定代码: ListView lstView = (ListView) this.findViewById(R.id.lis...

长平狐
2012/09/03
2.5K
0
SpringMVC源码(七)-View的多种实现

SpringMVC支持的视图有很多种,JSP的视图为JstlView,同时也支持其他模版:FreeMaker对应的视图为FreeMarkerView,Velocity对应的视图为VelocityView。另外还支持Excel及PDF的视图。 在Dispa...

青离
2017/10/25
0
0
JAVA学习笔记22——SpingMVC框架第二章

JAVA学习笔记22——SpingMVC框架第二章 Harries Blog™2017-12-210 阅读 ACESpringAppbeancatActionAjax 昨天讲解了 SpringMVC 的入门,今天来讲讲进阶一点的知识,话不多说,请看下文。 今天...

Harries Blog™
2017/12/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

70.shell的函数 数组 告警系统需求分析

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析 20.16/20.17 shell中的函数: ~1. 函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段...

王鑫linux
今天
2
0
分布式框架spring-session实现session一致性使用问题

前言:项目中使用到spring-session来缓存用户信息,保证服务之间session一致性,但是获取session信息为什么不能再服务层获取? 一、spring-session实现session一致性方式 用户每一次请求都会...

WALK_MAN
今天
5
0
C++ yield()与sleep_for()

C++11 标准库提供了yield()和sleep_for()两个方法。 (1)std::this_thread::yield(): 线程调用该方法时,主动让出CPU,并且不参与CPU的本次调度,从而让其他线程有机会运行。在后续的调度周...

yepanl
今天
4
0
Java并发编程实战(chapter_3)(线程池ThreadPoolExecutor源码分析)

这个系列一直没再写,很多原因,中间经历了换工作,熟悉项目,熟悉新团队等等一系列的事情。并发课题对于Java来说是一个又重要又难的一大块,除非气定神闲、精力满满,否则我本身是不敢随便写...

心中的理想乡
今天
34
0
shell学习之获取用户的输入命令read

在运行脚本的时候,命令行参数是可以传入参数,还有就是在脚本运行过程中需要用户输入参数,比如你想要在脚本运行时问个问题,并等待运行脚本的人来回答。bash shell为此提 供了read命令。 ...

woshixin
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部