Spring Form:提交大型对象列表时出现BindException

时间:2016-07-11 09:49:16

标签: java spring tomcat tomcat8 spring-form

我有表单,它在数据表中显示了几个对象列表。通过此表单,管理员用户可以为这些对象定义特定用户的权限。

例如,这是产品权限dataTable jsp代码:

<sf:form action="${action}" class="form-horizontal" method="post" modelAttribute="permisosList" enctype="multipart/form-data" >
...
<table class="table table-striped table-bordered table-hover" id="tabla_permisos6">
    <thead>
        <tr>
            <th><%=Languages.getString("Producto")%></th>
            <th><%=Languages.getString("Permiso")%></th>
        </tr>
    </thead>
    <tbody>
        <c:forEach items="${permisosList.permisosProducto}" var="permiso" varStatus="counter">
            <tr>
                <sf:input path="permisosProducto[${counter.index}].producto.idProd" type="hidden"/>
                <td style="vertical-align:middle;"><c:out value="${permiso.producto.nombre}"/></td>
                <td align="center">
                    <sf:select class="form-control" path="permisosProducto[${counter.index}].permiso" type="number">
                        <sf:option value="0">
                            <c:out value="No visible" />
                        </sf:option>
                        <sf:option value="1">
                            <c:out value="Visible" />
                        </sf:option>
                        <sf:option value="2">
                            <c:out value="Descarga" />
                        </sf:option>
                    </sf:select>
                </td>
            </tr>
        </c:forEach>
    </tbody>
</table>
...

其中一些列表中有数百或数千个对象,所以当我提交表单时,我得到了spring BindException :< / p>

  

org.springframework.validation.BindException:org.springframework.validation.BeanPropertyBindingResult:4个错误

     

对象&#39; permisosList&#39;中的字段错误on field&#39; permisosProducto [137] .producto.idProd&#39 ;:拒绝值[];代码[typeMismatch.permisosList.permisosProducto [137] .producto.idProd,typeMismatch.permisosList.permisosProducto.producto.idProd,typeMismatch.permisosProducto [137] .producto.idProd,typeMismatch.permisosProducto.producto.idProd,typeMismatch.idProd,typeMismatch。整型,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable:codes [permisosList.permisosProducto [137] .producto.idProd,permisosProducto [137] .producto.idProd];参数[];默认消息[permisosProducto [137] .producto.idProd]];默认消息[无法转换类型&#39; java.lang.String&#39;的属性值要求的类型&#39; int&#39; for property&#39; permisosProducto [137] .producto.idProd&#39 ;;嵌套异常是java.lang.NumberFormatException:对于输入字符串:&#34;&#34;]

     

对象&#39; permisosList&#39;中的字段错误on field&#39; permisosProducto [338] .permiso&#39 ;:拒绝价值[];代码[typeMismatch.permisosList.permisosProducto [338] .permiso,typeMismatch.permisosList.permisosProducto.permiso,typeMismatch.permisosProducto [338] .permiso,typeMismatch.permisosProducto.permiso,typeMismatch.permiso,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable:codes [permisosList.permisosProducto [338] .permiso,permisosProducto [338] .permiso];参数[];默认消息[permisosProducto [338] .permiso]];默认消息[无法转换类型&#39; java.lang.String&#39;的属性值要求的类型&#39; int&#39; for property&#39; permisosProducto [338] .permiso&#39 ;;嵌套异常是java.lang.NumberFormatException:对于输入字符串:&#34;&#34;]

     

对象&#39; permisosList&#39;中的字段错误on field&#39; permisosProducto [573] .permiso&#39 ;:拒绝价值[];代码[typeMismatch.permisosList.permisosProducto [573] .permiso,typeMismatch.permisosList.permisosProducto.permiso,typeMismatch.permisosProducto [573] .permiso,typeMismatch.permisosProducto.permiso,typeMismatch.permiso,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable:codes [permisosList.permisosProducto [573] .permiso,permisosProducto [573] .permiso];参数[];默认消息[permisosProducto [573] .permiso]];默认消息[无法转换类型&#39; java.lang.String&#39;的属性值要求的类型&#39; int&#39; for property&#39; permisosProducto [573] .permiso&#39 ;;嵌套异常是java.lang.NumberFormatException:对于输入字符串:&#34;&#34;]

     

对象&#39; permisosList&#39;中的字段错误on field&#39; permisosProducto [808] .permiso&#39 ;:拒绝价值[];代码[typeMismatch.permisosList.permisosProducto [808] .permiso,typeMismatch.permisosList.permisosProducto.permiso,typeMismatch.permisosProducto [808] .permiso,typeMismatch.permisosProducto.permiso,typeMismatch.permiso,typeMismatch.int,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable:codes [permisosList.permisosProducto [808] .permiso,permisosProducto [808] .permiso];参数[];默认消息[permisosProducto [808] .permiso]];默认消息[无法转换类型&#39; java.lang.String&#39;的属性值要求的类型&#39; int&#39; for property&#39; permisosProducto [808] .permiso&#39 ;;嵌套异常是java.lang.NumberFormatException:对于输入字符串:&#34;&#34;]

我已经检查过这些索引的信息是否正常,所以在任何地方都没有空字段(那么为什么一旦提交数据就会出现空字段?)。我也注意到那些索引并不总是相同的。也许如果我重新启动tomcat或者我稍后重试minuts,错误中的索引是不同的。 只有具有至少200多个对象的列表才会发生。并且在到达Controller之前抛出异常。

这是我的 PermisoList 类:

public class PermisoList {
    List<PermisoProductoForm> permisosProducto;
    List<PermisoCarpetaForm> permisosCarpeta;
    List<PermisoTipoDocForm> permisosTipoDoc;
    List<PermisoAgenteClienteForm> permisosAgenteCliente;
    List<PermisoIdiomaForm> permisosIdioma;
    List<PermisoPaisForm> permisosPais;
    List<PermisoEmpresaForm> permisosEmpresa;
    List<PermisoUsuarioProductoForm> permisosUsuarioProducto;   
...
}

我的 PermisoProductoForm 类:

public class PermisoProductoForm {

    private Producto producto;
    private int permiso;
...
}

我的 Producto 类:

@Entity
@Table(name = "Producto")
public class Producto {

    @Id
    @GeneratedValue
    private int idProd;

    private String codigo;
    private String nombre;
    private String marca;
    private boolean activo;

    @ManyToOne
    @JoinColumn(name = "idFamilia")
    private Familia familia;

    @OneToMany(mappedBy = "producto", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Documento> documentacion;

    @ManyToOne
    @JoinColumn(name = "idEmpresa")
    private Empresa empresa;

    @OneToMany(mappedBy = "primaryKey.producto", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<PermisoUsuarioProducto> permisosProducto;

    @OneToMany(mappedBy = "productoRelacionado", fetch = FetchType.LAZY)
    private List<TemaForo> temasForo;
...
}

另外,我已经尝试了一些解决方案,例如将此代码添加到控制器中:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setAutoGrowCollectionLimit(2048);
}

或者在jsp代码中的form标记内添加enctype="multipart/form-data"

有谁知道为什么会发生这种情况或知道如何解决这个问题?我现在100%被困住了。

编辑:我已经完成了@angcap的回答(将int更改为Integer类型并在initBinder方法中添加CustomEditor),现在这个BindException不再抛出了。所以控制器就到了。

现在发生的是那些空字符串的索引现在有一个&#39; null&#39;值(由于CustomEditor)。正如我所说,我在提交表单之前检查了信息,我可以看到列表中的所有对象都没问题,没有一个空字段的元素。

那么,当列表非常大时,为什么Spring会对数据执行此操作?它似乎是随机索引......

编辑2: 这是TOMCAT问题!我已部署在Pivotal tc服务器(v3.1)和binder.setAutoGrowCollectionLimit(2048);上解决方案,没有任何异常或空字符串或null。功能齐全。

问题出现在tomcat(v8.0)配置中。有谁知道这个?

编辑3:我接受@angcap答案,因为它确实解决了我的初始问题。通过他所说的避免BindException。

1 个答案:

答案 0 :(得分:0)

您似乎要为号码字段idProdpermiso发布空字符串。检查发布的数据或尝试在控制器中使用@initBinder注册CustomNumberEditor允许empyValues。