当前位置: 首页 > 知识库问答 >
问题:

selectOneMenu具有复杂对象,是否需要转换器?[复制]

袁泰平
2023-03-14

<p:selectOneMenu value="#{bean.language}">
    <f:selectItems value="#{bean.allLanguages}" />
</p:selectOneMenu>

@Named(value = "bean")
@ConversationScoped
public class Bean {

    private Language language; // appropriate getter and setter are present

    public List<SelectItem> getAllLanguages() {
        // populates a list of select items with Strings as item labels and Languages as item values
    }

}

我有一个类似的代码,带有enum作为类型(Language),它工作得很好。但是当我用普通的java类替换该类型时,我会得到一个转换错误。


共有2个答案

佴保臣
2023-03-14

如果您使用我编写的这个小类,您不需要转换器:-)它可以支持selectOne和selecte很多组件。它要求您的类的toString()提供对象的一对一唯一表示。如果您愿意,您可以替换toString()以外的方法名称,例如toIDString()

要在ManagedBean中使用ListBacker,请使用ListBacker

@ManagedBean
@RequestScoped
public class BackingBean {
    private ListBacker<User> users; // +getter +setter

    @PostConstruct
    public void init() {
        // fill it up from your DAO
        users = new ListBacker<User>(userDAO.find());
    }
    // Here's the payoff!  When you want to use the selected object, 
    // it is just available to you, with no extra database hits:
    User thisOneIsSelected = users.getSelectedItemAsObject();

    // or for multi-select components:
    List<User> theseAreSelected = users.getSelectedItemsAsObjects();
}

在您的xhtml文件中:

<p:selectOneMenu value="#{backingBean.users.selectedItem}">
    <f:selectItems value="#{backingBean.users.contents}" var="item" itemValue="#{item.value}" itemLabel="#{item.label}" />
</p:selectOneMenu>

ListBacker类:

public class ListBacker<T extends AbstractEntityBase> {
    // Contains the String representation of an Entity's ID (a.k.a.
    // primary key) and the associated Entity object
    Map<String, T> contents = new LinkedHashMap<String, T>(); // LinkedHashMap defaults to insertion-order iteration.

    // These hold values (IDs), not labels (descriptions).
    String selectedItem; // for SelectOne list
    List<String> selectedItems; // for SelectMany list


    public class ListItem {
        private String value;
        private String label;


        public ListItem(String value, String label) {
            this.value = value;
            this.label = label;
        }

        public String getValue() {
            return value;
        }

        public String getLabel() {
            return label;
        }
    }


    public ListBacker() {}

    public ListBacker(List<T> lst) {
        put(lst);
    }


    public void clear() {
        contents.clear();
        selectedItem = null;
        if(selectedItems != null) {
            selectedItems.clear();
        }
    }

    public List<ListItem> getContents() {
        return convert(contents);
    }

    public String getSelectedItem() {
        return selectedItem;
    }

    public void setSelectedItem(String selectedItem) {
        this.selectedItem = selectedItem;
    }

    public List<String> getSelectedItems() {
        return selectedItems;
    }

    public void setSelectedItems(List<String> selectedItems) {
        this.selectedItems = selectedItems;
    }

    public T getSelectedItemAsObject() {
        return convert(selectedItem);
    }

    public List<T> getSelectedItemsAsObjects() {
        return convert(selectedItems);
    }


    public void put(T newItem) {
        contents.put(newItem.toString(), newItem);
    }

    public void put(List<T> newItems) {
        for (T t : newItems) {
            put(t);
        }
    }


    // PROTECTED (UTILITY) METHODS

    protected List<ListItem> convert(Map<String, T> maps) {
        List<ListItem> lst = new ArrayList<ListItem>();
        for (Entry<String, T> e : maps.entrySet()) {
            lst.add(new ListItem(e.getKey(), e.getValue().desc()));
        }
        return lst;
    }

    protected List<T> convert(List<String> ids) {
        List<T> lst = new ArrayList<T>();
        for (String id : ids) {
            lst.add(convert(id));
        }
        return lst;
    }

    protected T convert(String id) {
        return contents.get(id);
    }

}

我有两个toString()实现,一个用于JPA实体:

public abstract class AbstractEntityBase {
    @Override
    public final String toString() {
        return String.format("%s[id=%s]", getClass().getSimpleName(), getIdForToString().toString());
    }
    /**
    * Return the entity's ID, whether it is a field or an embedded ID class..
    * @return ID Object
    */
    protected abstract Object getIdForToString();
}

还有一个是JPA EmbeddedId的:

public abstract class CompositeKeyBase {
    @Override
    public final String toString() {
        return String.format("%s[id=%s]", getClass().getSimpleName(), getIdForToString());
    }

    /**
     * Supports the class's toString() method, which is required for ListBacker.
     * Compile a string of all ID fields, with this format:
     * fieldName=StringVALUE,field2=STRINGvAlUE2,...,fieldx=stringvalue <br />
     * Recommended: start with Eclipse's "generate toString()" utility and move it to getIdForToString()
     * @return a 1-to-1 String representation of the composite key
     */
    public abstract String getIdForToString();
}

getIdForToString()的一个示例实现,用于具有一个Id字段的实体:

@Override
public Object getIdForToString() {
    return userID;
}

getIdForToString()的一个示例实现,用于具有两个字段的EmbeddedId:

@Override
public String getIdForToString() {
    return "userID=" + userID + ",roleID=" + roleID;
}

陈飞
2023-03-14

您在这里需要一个转换器,因为JSF默认会假设字符串,这就是您编码它的方式。JSF不知道如何将您的伪实体转换为字符串,反之亦然。

注意:

1.您的getAsString方法定义了实体/pojo的标识符,而不是JSF(或其他)select作为itemLabel获得的标识符。

2.您的转换器可以使用这篇臭名昭著的文章深入到数据库中寻找真正的实体:

http://balusc.blogspot.de/2011/09/communication-in-jsf-20.html#ConvertingAndValidatingGETRequestParameters

您还可以使用具有该“模式”的CDI注释。

3.您的value="bean"是多余的,CDI的选择范围通常是@ViewScoped。但是,您必须记住,CDI@命名JSF@ViewScoped在不使用Seam 3或Apache MyFaces CODI的情况下无法协同工作。

 类似资料:
  • 所以,问题是当我试图通过转换器!这是枚举转换器(使用@FacesConverter(value=“TipoCampoConverter”)注释扩展EnumConverter) 错误为:javax.el.elException:无法将类java.lang.String类型的tipoCampoConverter转换为接口javax.faces.convert.Converter **编辑:

  • 问题内容: 我有一个应用程序,该应用程序使用Jackson将我的复杂对象编组为JSON,从而在DynamoDB中存储一些数据。 例如,我要编组的对象可能如下所示: SomeObject可能看起来像这样: 和SomeOtherObject可能看起来像这样: 可以很好地将对象整理成问题并将其作为JSON字符串存储在数据库中。 当需要从DynamoDB检索数据时,Jackson会自动检索JSON并将其转

  • 某个物体可能看起来像这样: 另一个物体可能是这样的: 这很好,因为对象被封送,没有问题,并以JSON字符串的形式存储在DB中。

  • 我正在用查询构建一个存储库,该查询使用一个复杂的类型参数进行筛选,如下所示: 类是一个简单的POJO: null 谢了!

  • 这里有几个关于如何检查对象中是否存在属性的答案。 我一直在使用 但我想知道这和

  • 我想检查一个对象是否有新的子对象。我的意思是我有一个带有x嵌套对象的对象,但是如果主对象有新对象,我会检查它。有什么现有的解决方案来检查这个问题吗? 我的目标是如果对象有新项目,则调用函数。每次数组更改时,此代码都会调用该函数。也当一些项目被删除。这部分功能是错误的。有办法修好它吗?