通过缓存数据客户端避免在转换器类的 getAsObject 方法中进行额外的数据库读取? [英] Avoid extra DB reads in the getAsObject method of converter class by caching data client side?
问题描述
我在 autocomplete
输入元素中显示了建议项目的列表.为此,我需要实现一个 converter
来将 entity
转换为 entityName
&反之亦然.但是,在实施时,我意识到我必须读取数据库超过 1 次才能找到所选实体名称的相应实体 ID(而 getAsObject()
),我想知道为什么不将其存储在某处客户端,以便在选择 entityname
时可以传递 entityId
.
I'm showing a list of suggested items in an autocomplete
input element. For that I need to implement a converter
to convert the entity<entityName, entityId>
to entityName
& vice versa. However while implementing that I realized that I had to read the DB more than 1 time to find the corresponding entityId for the chosen entityName(while getAsObject()
), I am wondering why isn't this stored somewhere client side so that the entityId
could be passed when the entityname
is selected.
有什么办法可以避免这种额外的阅读吗?
Is there any way I could avoid this extra read?
推荐答案
这确实是设计使然",也许是 JSF 规范中的一个小疏忽.理论上,您可以通过从 UIComponent
参数中提取项目并与它们进行比较来完全避免它.然而,这有点工作.我的同事 Arjan Tijms 写了一篇关于这个的博客:JSF selectOneMenu & 中的自动对象转换公司
This is indeed "by design" and perhaps a little oversight in the JSF spec. You can in theory perfectly avoid it by extracting the items from the UIComponent
argument and comparing against them instead. It's however a bit of work. My colleague Arjan Tijms has written a blog about this: Automatic to-Object conversion in JSF selectOneMenu & Co.
这是相关性的摘录;以下是您需要扩展的基本转换器:
Here's an extract of relevance; the below is the base converter which you'd need to extend instead:
public abstract class SelectItemsBaseConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return SelectItemsUtils.findValueByStringConversion(context, component, value, this);
}
}
这是部分从 Mojarra 的源代码中复制的 SelectItemsUtils
类:
Here's the SelectItemsUtils
class which is partly copied from Mojarra's source:
public final class SelectItemsUtils {
private SelectItemsUtils() {}
public static Object findValueByStringConversion(FacesContext context, UIComponent component, String value, Converter converter) {
return findValueByStringConversion(context, component, new SelectItemsIterator(context, component), value, converter);
}
private static Object findValueByStringConversion(FacesContext context, UIComponent component, Iterator<SelectItem> items, String value, Converter converter) {
while (items.hasNext()) {
SelectItem item = items.next();
if (item instanceof SelectItemGroup) {
SelectItem subitems[] = ((SelectItemGroup) item).getSelectItems();
if (!isEmpty(subitems)) {
Object object = findValueByStringConversion(context, component, new ArrayIterator(subitems), value, converter);
if (object != null) {
return object;
}
}
} else if (!item.isNoSelectionOption() && value.equals(converter.getAsString(context, component, item.getValue()))) {
return item.getValue();
}
}
return null;
}
public static boolean isEmpty(Object[] array) {
return array == null || array.length == 0;
}
/**
* This class is based on Mojarra version
*/
static class ArrayIterator implements Iterator<SelectItem> {
public ArrayIterator(SelectItem items[]) {
this.items = items;
}
private SelectItem items[];
private int index = 0;
public boolean hasNext() {
return (index < items.length);
}
public SelectItem next() {
try {
return (items[index++]);
}
catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
这里是你应该如何将它用于你自己的转换器,你只需要实现 getAsString()
(getAsObject()
已经处理了):
Here's how you should use it for your own converter, you only have to implement getAsString()
(the getAsObject()
is already handled):
@FacesConverter("someEntitySelectItemsConverter")
public class SomeEntitySelectItemsConverter extends SelectItemsBaseConverter {
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return ((SomeEntity) value).getId().toString();
}
}
<小时>
更新上述概念已在 JSF 实用程序库 OmniFaces 中以以下转换器:
Update the above concept has ended up in JSF utility library OmniFaces in flavor of the following converters:
SelectItemsConverter
- 对于<f:selectItem(s)>
基于Object#toString()
.SelectItemsIndexConverter
- 对于<f:selectItem(s)>
基于项目的索引.ListConverter
- 例如
基于Object#toString()
ListIndexConverter
- 例如
基于项目的索引.
SelectItemsConverter
- for<f:selectItem(s)>
based onObject#toString()
.SelectItemsIndexConverter
- for<f:selectItem(s)>
based on item's index.ListConverter
- for e.g.<p:autoComplete>
based onObject#toString()
ListIndexConverter
- for e.g.<p:autoComplete>
based on item's index.
这篇关于通过缓存数据客户端避免在转换器类的 getAsObject 方法中进行额外的数据库读取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!