2

我正在使用 Spring MVC 和 Spring Data,并且还配置了 Spring DataDomainClassConverter以自动将 String id 转换为适当的 Domain 类。

我现在正在使用以下标签实现 Order to Customer 参考:

<form:select path="customer">
    <form:option value="" label="Select" />
    <form:options items="${customers}" itemValue="id" />
</form:select>

这导致给定的HTML:

<select id="customer" name="customer" class="span6">
    <option value="">Select</option>
    <option value="1">Customer A</option>
    <option value="2">Customer B</option>
    <option value="3">Customer C</option>
</select>

当提交选择客户 A 的帖子时,我得到一个例外,例如:

org.apache.jasper.JasperException: org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @javax.validation.constraints.NotNull @javax.persistence.ManyToOne nl.kapsalonreflection.domain.Customer for value ''; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: The given id must not be null!; nested exception is java.lang.IllegalArgumentException: The given id must not be null!

这根本没有意义,因为收到的值应该是 1 而不是 ''。我还调试了收到的请求参数,它只包含 customer=1 (如预期的那样)

请注意,它InvalidDataAccessApiUsageException来自 Spring Data DomainClassConverter,如果我删除了这个转换器,问题就不会再发生了。

我还调试了DomainClassConverter它,我可以看到它试图覆盖两次。首先使用字符串值 1(如预期的那样),然后使用空字符串进行另一个调用,导致异常。

然而它变得更奇怪了......

当我<form:option value="" label="Select" />用普通的 html 元素替换时<option value="">Select</option>,不会发生异常,因此只使用字符串 1 对 convert 方法进行 1 次调用。奇怪的部分是两者都<form:option value="" label="Select" />产生<option value="">Select</option>相同的 html 输出......

我无法解释这种行为......虽然我似乎有一个使用普通 html 元素的“解决方法”,但我想知道是什么导致了这个问题。

4

2 回答 2

6

请注意,org.apache.jasper.JasperException表示异常发生在 JSP 呈现期间,而不是在数据绑定期间。这与异常依赖的事实一致<form:option value="" label="Select" />- 在回发后呈现表单时正在处理此标记时抛出它。

您观察到的行为可以解释如下:为了确定其选定状态<form:option>,尝试将其值与绑定到的字段的值进行比较<form:select>。如果绑定字段的值为null<form:option>只需将其值与 进行比较null,这就是为什么在初始表单呈现期间不会出现此异常的原因。否则,<form:option>尝试将其转换<value>为绑定字段的类型,并value = ""在此步骤引发异常。

因此,您应该使用null“未选择选项”值而不是空字符串:

<form:option value="${null}" label="Select" /> 
于 2012-09-14T23:08:04.613 回答
0

在这种情况下,您可能需要考虑附加一个属性编辑器,因为如果我看到<form:options items="${customers}" itemValue="id" />您直接将客户列表附加到选项的代码。我认为它自动获取 toString 并显示“客户 A”、“客户 B”等。理想情况下,您可能需要在 form:options 标记中使用 itemLabel,或者您可能需要注册一个属性编辑器并将其附加到 initBinder http://static.springsource.org/spring/docs/2.5.x/reference/validation.html#beans-beans-conversion

于 2012-09-14T22:18:03.863 回答