代码之家  ›  专栏  ›  技术社区  ›  Zim

正在检索selectOneMenu复杂对象作为所选项目

  •  1
  • Zim  · 技术社区  · 11 年前

    我从JSF(Mojarra 2.2和Glassfish 4)开始,目前正在练习一个web应用程序,该应用程序的工作是将客户端及其订单存储在DB中。

    当创建一个新的Order时,一个特性是允许从JSF中选择一个现有的客户端 <h:selectOneMenu> 。Order实体存储Client实体以及其他属性。。。

    我遵循了BalusC关于预填充 <h: 选择一个菜单> 来自数据库( here ),并且已经成功地从存储在一个急切的ApplicationScoped ManagedBean中的数据中填充了我的,但我无法将backingbean中的所选项目作为复杂对象检索。它总是空的。

    这让我抓狂,我们将非常感谢您的帮助! 以下是相关的代码片段:

    @ManagedBean(eager = true)
    @ApplicationScoped
    public class Data implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @EJB
        private ClientDao clientDao;
    
        private List<Client> clients;
    
        @PostConstruct
        private void init() {
            clients = clientDao.lister();
        }
    
        public List<Client> getClients() {
            return clients;
        }
    
    }
    

    订单创建bean(注意:“command”表示订单;)

    @ManagedBean
    @RequestScoped
    public class CreerCommandeBean implements Serializable {
        private static final long serialVersionUID = 1L;
        private Commande commande;
    
        private String choixNouveauClient = "nouveauClient";
    
        @EJB
        private CommandeDao commandeDao;
    
        public CreerCommandeBean() {
            commande = new Commande();
        }
    
        public void inscrire() {
    
            System.out.println("client : " + commande.getClient()); // prints **NULL**
                // ... orderService to store in DB
        }
    ... getters and setters
    

    客户端转换器:

    @FacesConverter(value = "clientConverter", forClass = Client.class)
    public class ClientConverter implements Converter {
    
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
            if (value == null) {
                return null;
            }
    
            Data data = context.getApplication().evaluateExpressionGet(context, "#{data}", Data.class);
            for (Client c : data.getClients()) {
                if (c.getId().toString().equals(value)) {
                    return c;
                }
            }
            throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Client", value)));
        }
    
        @Override
        public String getAsString(FacesContext context, UIComponent component, Object value) {
            return (value instanceof Client) ? String.valueOf(((Client) value).getId()) : null;
        }
    }
    

    Facelet摘录:

    <p:outputPanel id="gridContainerAncienClient">
                <p:selectOneMenu value="#{creerCommandeBean.commande.client}"
                    rendered="#{creerCommandeBean.choixNouveauClient == 'ancienClient'}">
                    <f:converter converterId="clientConverter" />
                    <f:selectItems value="#{data.clients}" var="cli"
                        itemValue="#{cli}" itemLabel="#{cli.prenom} #{cli.nom}" />
                </p:selectOneMenu>
            </p:outputPanel>
    
    2 回复  |  直到 8 年前
        1
  •  1
  •   Lester    11 年前

    CreerCommandeBean @RequestScoped 。这意味着它将只为一个请求而存在。
    当您选择要分配给的客户端时 #{creerCommandeBean.commande.client} 你这样做是有要求的。 #{creerCommandeBean命令客户端} 现在是选定的客户端。然后请求结束,bean被销毁,您的“更改”也会丢失。
    当您尝试检索该数据时,您会再次通过请求来检索: 爬行通用Bean 创建,构造函数分配属性 commande 具有的新实例 Commande 其财产 client 可能又是 null .

    解决方案:
    使用更广泛的范围。例如 @ViewScoped 只要你保持在同一个视图中,无论你发出多少请求,这都会使bean“活”起来。

    提示: 阅读 BalusC's Post on Communication is JSF 2.0 。JSF 2.2中的部分可能略有不同,但它仍然是一个很好的、全面的介绍。

        2
  •  0
  •   Kukeltje    4 年前

    我遇到了类似的问题,结果发现我忘记在Object中实现equals()和hashCode()方法。在这种情况下,客户端类。

    我应该怪自己跳过了中的说明 BalusC's blog .

    “…请注意 Object#equals() 实施 这对JSF来说非常重要。 转换后,它会将所选项目与列表中的项目进行比较。作为 对象#equals() 也需要 Object#hashCode() ,这也得到了实施。。。。"