0

我正在尝试从 JSF SelectOneMenu 组件获取客户实体:我拥有的类如下:

客户实体

@Entity
@Table(name="CUSTOMERS")
@NamedQuery(name="Customer.findAll", query="SELECT c FROM Customer c")
public class Customer implements Serializable {

    @Id
    @GeneratedValue
    @Column(name="CUSTOMER_ID")
    private Long customerId;

    @Column(name="FIRST_NAME")
    private String firstName;

    @Column(name="LAST_NAME")
    private String lastName;

    private String email;

    public Long getCustomerId() {  
        return customerId;
    }

    public void setCustomerId(Long customerId) {
        this.customerId = customerId;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        Long localCustomerId = customerId;
        String localFirstName = firstName;
        String localLastName = lastName;
        String localEmail = email;
        if (localCustomerId == null) {
            localCustomerId = 0L;
        }
        if (localEmail == null) {
            localEmail = "";
        }
        if (localFirstName == null) {
            localFirstName = "";
        }
        if (localLastName == null) {
            localLastName = "";
        }

        String toString = "customerId = " + localCustomerId + "\n";
        toString += "firstName = " + localFirstName + "\n";
        toString += "lastName = " + localLastName + "\n";
        toString += "email = " + localEmail;

        return toString;
    }

}

客户控制器

 @ManagedBean
    @RequestScoped
    public class CustomerController implements Serializable {
    private static final long serialVersionUID = 1L;

    @Resource(name = "jdbc/__CustomerDBPool")
    private DataSource dataSource;

    @PersistenceUnit(unitName = "customerPersistenceUnit")
    private EntityManagerFactory emf;

    @Resource
    private UserTransaction userTransaction;

    @ManagedProperty(value = "#{customer}")
    private Customer customer;


    public DataSource getDataSource() {
        return dataSource;
    }

    public EntityManagerFactory getEmf() {
        return emf;
    }

    public void saveCustomer() {
        EntityManager entityManager = emf.createEntityManager();
        try {
            userTransaction.begin();
            entityManager.persist(customer);
            userTransaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void setEmf(EntityManagerFactory emf) {
        this.emf = emf;
    }

    public List<Customer> getCustomerList() {

        List<Customer> list = null;
        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createNamedQuery("Customer.findAll");
            int m = q.getResultList().size();

            list = (List<Customer>)  q.getResultList();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    public Customer getCustomerById(Long id) {
        EntityManager entityManager = emf.createEntityManager();
        Query q = entityManager.createQuery("Select c FROM Customer c WHERE c.id = :id");
        q.setParameter("id", id);
        Customer c = (Customer) q.getResultList().get(q.getFirstResult());
        return c;
    }

    public String getCustomerDetails() {
        if (customer == null)
            return "NULL";
        else
            return customer.toString();
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
        //System.out.println(customer);
    }
    }

客户转换器

@ManagedBean
@RequestScoped
@FacesConverter(value = "CustomerConverter")
    public class CustomerConverter implements Converter, Serializable {

        @ManagedProperty(value = "#{cController}")
        private CustomerController cc;

        @Override
        public Object getAsObject(FacesContext context, UIComponent component,
                String value) {

            Long pk = Long.parseLong(value);
            Customer c = null;
            List<Customer> list = (List<Customer>) cc.getCustomerList();
            for (Customer k : list) {
                if (k.getCustomerId().equals(pk))
                        c = k;
            }

            return c;
        }

        @Override
        public String getAsString(FacesContext context, UIComponent component,
                Object value) {
            Long id = (Long) value;
            return id.toString();
        }

        public CustomerController getCc() {
            return cc;
        }

        public void setCc(CustomerController cc) {
            this.cc = cc;
        }
    }

最后是 .xhtml 文件

<h:head>
    <title>Save Customer</title>
</h:head>

<h:body>
    <h:panelGrid columns="1">

        <h:form>
            <h:messages id="messages"></h:messages>
            <p/>
            <h:selectOneMenu id="select1" value="#{customerController.customer}" converter="CustomerConverter">

                <f:selectItems 
                    value="#{customerController.customerList}" var="c"
                    itemLabel="#{c.customerId} #{c.firstName} #{c.lastName}"
                    itemValue="#{c.customerId}"/>
            </h:selectOneMenu>
            <p/>
            <h:commandButton value="Output" update="output2"></h:commandButton>

            <p/>
            <h:outputText id="output2" value="#{customerController.customerDetails}"/>
        </h:form>

    </h:panelGrid>
</h:body>
</html>

基本上,我似乎无法使用 CustomerConverter bean 实例化 CustomerController bean。任何想法我做错了什么?

4

2 回答 2

1

我认为使用@ManagedBeanand@FacesConverter是一件非常非常糟糕的事情。托管 bean 必须负责视图处理。转换器用于转换值。
代码中另一个糟糕的设计点是,您直接从托管 bean 访问 DB,这又是非常糟糕的。您必须为数据访问定义另一个层(DAO 层)。
假设您CustomerDAO为客户访问定义了一个。然后,您将轻松访问CUSTOMERS托管 bean 中的表,也可以通过您的 DAO 访问转换器中的表。

于 2013-05-17T20:33:12.303 回答
1

这里,

@ManagedBean
@RequestScoped
@FacesConverter(value = "CustomerConverter")
public class CustomerConverter implements Converter, Serializable {

您已经注册了 2 个不同的类托管实例:一个是 as @ManagedBean,另一个是@FacesConverter.

每当您在 EL 上下文中的任何位置使用时,都会返回#{customerConverter}一个请求范围的托管 bean 实例,其中 bean已正确注入。@ManagedBean@ManagedProperty

每当您converter="CustomerConverter"在视图中的任何位置使用时,都将返回来自的 faces 转换器实例@FacesConverter,其中根本不支持依赖注入。

这个不对。这令人困惑。只需摆脱@FacesConverter并使用

converter="#{customerConverter}"

与具体问题无关:在 JSF 托管 bean 中混合业务服务和 JPA 逻辑是一种非常糟糕的做法。您应该为此使用一个完全值得的 EJB。您可以在以下相关问题中找到具体示例:

于 2013-05-19T02:12:42.390 回答