我在 Spring MVC 中使用自定义编辑器将字符串值映射到我的域对象。简单情况:用户对象指的是公司(User.company -> Company)。在用户表单中,我注册了数据绑定(bind)器:
protected void initBinder(WebDataBinder binder) throws Exception {
binder.registerCustomEditor(Company.class, new CompanyEditor(appService));
}
编辑器定义如下:
class CompanyEditor extends PropertyEditorSupport {
private AppService appService;
public CompanyEditor(AppService appService) {
this.appService = appService;
}
public void setAsText(String text) {
Company company = appService.getCompany(text);
setValue(company);
}
public String getAsText() {
Company company = (Company) this.getValue();
if (company != null)
return company.getId();
return null;
}
}
当我在表单中使用下拉菜单时
<form:select path="company">
<form:options items="${companies}" itemLabel="name" itemValue="id"/>
</form:select>
我遇到了严重的性能问题,因为(我想是为了检查公司是否被选中)为每个选项触发 setAsText 和 getAsText,这使得它为每个公司运行一个 SQL 查询。
我认为当我提交表单时使用 setAsText 使应用程序知道如何将 compnany id 转换为 Company(持久)对象。为什么要在下拉菜单中触发它。有什么解决办法吗?
最佳答案
如果您的表单支持对象存储为 session 属性(即您的 Controller 中有类似 @SessionAttributes("command")
的东西),那么您可以尝试修改您的 setAsText(字符串文本)
方法
public void setAsText(String text) {
Company currentCompany = (Company) this.getValue();
if ((currentCompany != null) && (currentCompany.getId().equals(text)))
return;
Company company = appService.getCompany(text);
setValue(company);
}
但我认为Spring 3.1 @Cacheable abstraction正是为这类事情而引入的,并且更可取
查看文档中的示例
@Cacheable("books")
public Book findBook(ISBN isbn) {...}
附言考虑使用新的 Converter SPI而不是属性编辑器。
通常,可以为您的查找实体实现一个通用转换器,因此如果实体具有某些特定属性,它将使用 id 自动从文本转换实体,例如,在我的一个项目中所有 @实体
类型正在使用全局 ConditionalGenericConverter 自动转换实现,因此我既没有在绑定(bind)期间注册自定义属性编辑器,也没有为带有 @Id
注释主键的简单 @Entity
类实现特定转换器。
当 Spring 将文本对象 ID 指定为 @RequestParam
注释 Controller 方法参数时自动将它们转换为实际实体时,这也非常方便。
关于forms - Spring MVC 自定义编辑器和选择选项性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11896714/