database - 如何填充 h :selectOneMenu from database? 的选项

标签 database jsf selectonemenu

我正在创建一个 Web 应用程序,您必须在其中从数据库中读取对象/实体列表并将其填充到 JSF 中 <h:selectOneMenu> .我无法对此进行编码。谁能告诉我怎么做?

我知道如何获得 List<User>从数据库。我需要知道的是,如何在 <h:selectOneMenu> 中填充此列表.

<h:selectOneMenu value="#{bean.name}">
    ...?
</h:selectOneMenu>

最佳答案

根据您的问题历史记录,您使用的是 JSF 2.x。所以,这是一个针对 JSF 2.x 的答案。在 JSF 1.x 中,您将被迫用丑陋的 SelectItem 包装项目值/标签。实例。幸运的是,在 JSF 2.x 中不再需要了。


基本示例

要直接回答您的问题,只需使用 <f:selectItems> 谁的value指向 List<T>在 bean 的(后期)构造期间从数据库中保留的属性。这是一个基本的启动示例,假设 T实际上代表一个String .

<h:selectOneMenu value="#{bean.name}">
    <f:selectItems value="#{bean.names}" />
</h:selectOneMenu>

@ManagedBean
@RequestScoped
public class Bean {

    private String name;
    private List<String> names; 

    @EJB
    private NameService nameService;

    @PostConstruct
    public void init() {
        names = nameService.list();
    }

    // ... (getters, setters, etc)
}

就这么简单。实际上,TtoString()将用于表示下拉项标签和值。所以,当你不是 List<String>使用复杂对象列表,如 List<SomeEntity>而且你还没有覆盖类'toString()方法,那么你会看到 com.example.SomeEntity@hashcode作为项目值。请参阅下一节如何正确解决它。

另请注意 <f:selectItems> 的 bean value 不一定需要与 <h:selectOneMenu> 的 bean 相同值(value)。当值实际上是应用程序范围的常量时,这很有用,您只需在应用程序启动期间加载一次。然后,您可以将其设为应用程序作用域 bean 的属性。

<h:selectOneMenu value="#{bean.name}">
    <f:selectItems value="#{data.names}" />
</h:selectOneMenu>

作为可用项的复杂对象

每当T涉及复杂对象(javabean),例如User它有一个 String name的属性(property), 那么你可以使用 var属性来获取迭代变量,您又可以在 itemValue 中使用它和/或 itemLabel属性(如果省略 itemLabel ,则标签将与值相同)。

示例#1:

<h:selectOneMenu value="#{bean.userName}">
    <f:selectItems value="#{bean.users}" var="user" itemValue="#{user.name}" />
</h:selectOneMenu>

private String userName;
private List<User> users;

@EJB
private UserService userService;

@PostConstruct
public void init() {
    users = userService.list();
}

// ... (getters, setters, etc)

或者当它有一个 Long属性(property)id您希望将其设置为项目值:

示例 #2:

<h:selectOneMenu value="#{bean.userId}">
    <f:selectItems value="#{bean.users}" var="user" itemValue="#{user.id}" itemLabel="#{user.name}" />
</h:selectOneMenu>

private Long userId;
private List<User> users;

// ... (the same as in previous bean example)

作为选定项的复杂对象

每当您想将其设置为 T bean 中的属性以及 T代表一个 User ,那么您需要烘焙自定义 Converter User 之间转换和一个唯一的字符串表示(可以是 id 属性)。请注意 itemValue必须表示复杂对象本身,正是需要设置为选择组件的类型 value .

<h:selectOneMenu value="#{bean.user}" converter="#{userConverter}">
    <f:selectItems value="#{bean.users}" var="user" itemValue="#{user}" itemLabel="#{user.name}" />
</h:selectOneMenu>

private User user;
private List<User> users;

// ... (the same as in previous bean example)

@ManagedBean
@RequestScoped
public class UserConverter implements Converter {

    @EJB
    private UserService userService;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        if (submittedValue == null || submittedValue.isEmpty()) {
            return null;
        }

        try {
            return userService.find(Long.valueOf(submittedValue));
        } catch (NumberFormatException e) {
            throw new ConverterException(new FacesMessage(String.format("%s is not a valid User ID", submittedValue)), e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
        if (modelValue == null) {
            return "";
        }

        if (modelValue instanceof User) {
            return String.valueOf(((User) modelValue).getId());
        } else {
            throw new ConverterException(new FacesMessage(String.format("%s is not a valid User", modelValue)), e);
        }
    }

}

(请注意 Converter 有点 hacky,以便能够在 JSF 转换器中注入(inject) @EJB;通常人们会将其注释为 @FacesConverter(forClass=User.class)but that unfortunately doesn't allow @EJB injections)

不要忘记确保复杂对象类具有 equals() and hashCode() properly implemented ,否则 JSF 将在渲染期间无法显示预选项目,并且您将在提交面上 Validation Error: Value is not valid .

public class User {

    private Long id;

    @Override
    public boolean equals(Object other) {
        return (other != null && getClass() == other.getClass() && id != null)
            ? id.equals(((User) other).id)
            : (other == this);
    }

    @Override
    public int hashCode() {
        return (id != null) 
            ? (getClass().hashCode() + id.hashCode())
            : super.hashCode();
    }

}

具有通用转换器的复杂对象

前往此答案:Implement converters for entities with Java Generics .


没有自定义转换器的复杂对象

JSF 实用程序库 OmniFaces提供开箱即用的特殊转换器,允许您在 <h:selectOneMenu> 中使用复杂对象无需创建自定义转换器。 SelectItemsConverter 将根据 <f:selectItem(s)> 中现成的项目简单地进行转换.

<h:selectOneMenu value="#{bean.user}" converter="omnifaces.SelectItemsConverter">
    <f:selectItems value="#{bean.users}" var="user" itemValue="#{user}" itemLabel="#{user.name}" />
</h:selectOneMenu>

另见:

关于database - 如何填充 h :selectOneMenu from database? 的选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6848970/

相关文章:

mysql - 如何从数据库中删除少于3个字符的单词

php - 使用 PDO 获取单行单列

jsf - 用逗号格式化为数字 JSF

jsf - p :inplace when it's clicked 后面自动打开selectOneMenu

jsf - 如何预选 h :selectOneMenu 的选项

android - ListView 和自定义 ListView

java - 如何在Struts 2中显示图像?

java - 如何在 JSF 中检索 DIV 宽度

java - 带有 Cocoon 的 JSF

jsf - <h :selectBooleanCheckbox> is not updated according to backing bean value 的值