Reputation: 544
Im using custom editor in Spring MVC to map string valuest to my domain objects. Simple case: User object refers to Company (User.company -> Company). In User form I register data binder:
protected void initBinder(WebDataBinder binder) throws Exception {
binder.registerCustomEditor(Company.class, new CompanyEditor(appService));
}
Editor is defined as folows:
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;
}
}
When I use dropdown in my form
<form:select path="company">
<form:options items="${companies}" itemLabel="name" itemValue="id"/>
</form:select>
I experience severe performance problems because (to check if company is selected, I suppose) fires setAsText and getAsText for each option, which makes it to run a SQL query for each company.
I thought that setAsText is used when I commit form to make application know how to translate compnany id to Company (persisted) object. Why should it fire it in dropdowns. Any ideas how to fix it?
Upvotes: 3
Views: 2842
Reputation: 17784
If your form backing object is stored as session attribute(i.e. you have something like @SessionAttributes("command")
in your controller), so you can try to modify your setAsText(String text)
method
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);
}
but I think that Spring 3.1 @Cacheable abstraction was introduced exactly for the such kind of things and is preferable
see examples in documentation
@Cacheable("books")
public Book findBook(ISBN isbn) {...}
P.S. Consider using new Converter SPI instead of Property Editors.
In general, it's possible to implement a generic converter for your look-up entities, so it will automatically convert entities from text using id if they have some specific attribute, for example, in one of my projects all @Entity
types are being automatically converted using a global ConditionalGenericConverter implementation, so I neither register custom property editors during binding nor implement specific converters for types which are simple @Entity
classes with @Id
annotated primary keys.
Also it's very convenient when Spring automatically converts textual object ids to the actual entities when they are specified as @RequestParam
annotated controller method arguments.
Upvotes: 2