使用JAVA持久性将数据保存到jpa中的外键属性,并使用eJB将数据保存到下拉元素



嗨,我想使用JPA将数据表单JSP文件保存到Derby数据库中,但是无法将数据保存到数据库中。在产品订单页面中:我需要保存值

public class ProductOrder implements Serializable {
    @ManyToOne
    @JoinColumn(name = "customerId")
    private Customer customer;
    //getter 
    //setter
}

在EJB文件中:

public class OrderEJB {
    @PersistenceContext(unitName = "com.mycompany_Ebusiness_war_1.0-SNAPSHOTPU")
    private EntityManager entityManager;
    public ProductOrder placeOrder(ProductOrder productOrder) {
        entityManager.persist(productOrder);
        return productOrder;
    }
}

在JSP(XHTML文件)文件中:

<h:form>
    <h:selectOneMenu value="#{orderController.customer}" >
        <f:selectItems value="#{orderController.customerList}" var="c" itemLabel="#{c.name}" itemValue="#{c.id}" />
    </h:selectOneMenu>
    <h:commandButton value="Place a Order" action="#{orderController.placeOrder}"/>
</h:form>

我的转换器文件:

public class CustomerConverter implements Converter{ 
    private transient EntityManager em; 
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) { 
        return em.find(Customer.class, new Integer(value));
    }
    @Override
    public String getAsString(FacesContext fc, UIComponent uic, Object o) { 
        return ((Customer) o).getId().toString(); 
    }
}

代码错误

您的代码包含一些错误/缺失点:

  1. 缺少可选的引用columnname :如注释中所述,JoinColumn注释缺少属性。该属性是可选的,但我喜欢确保引用的内容:

    public class ProductOrder implements Serializable {
        @ManyToOne
        // replace "id" with the appropriate column name
        @JoinColumn(name = "customerId", referencedColumnName = "id")
        private Customer customer;
        //getter 
        //setter
    }
    

    referencedColumnNameFOREIGN KEY并行。以上注释反映了约束:

    FOREIGN KEY (customerId) REFERENCES customer_table(id)
    
  2. 您正在使用 JSF,而不是JSP 。请参阅此问题以获取更多信息。

  3. 您的selectOneMenu不正确:

    <h:form>
        <h:selectOneMenu value="#{orderController.customer}" converter="customerConverter">
            <f:selectItems value="#{orderController.customerList}" var="c"
                           itemLabel="#{c.name}" itemValue="#{c}" />
        </h:selectOneMenu>
        <h:commandButton value="Place a Order" action="#{orderController.placeOrder}"/>
    </h:form>
    
    • 缺少转换器标签。Balusc在这里提供了一个很棒的解释。
    • 您的 itemValue 应该参考您的客户对象,而不是客户ID。因此,应该是itemValue="#{c}
  4. 您正在转换错误的值:转换器类转换customerId <-> customer object,而在SelectoneMenu中,您要转换customer name <-> customer object

  5. 您的转换器类可能缺少@FacesConverter注释

解决

您需要一个一个一个地解决每个点:

  1. 转换器:选择要显示的内容,如果要显示客户名称,则转换器应该看起来像:

    @FacesConverter
    @RequestScoped
    public class CustomerConverter implements Converter{ 
        // you would normally inject your EJB here. Please refer to BalusC's 
        // answer for more information
        // private transient EntityManager em;
        @EJB
        private CustomerService customerService;
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
            return customerService.findByName(value);
        }
        @Override
        public String getAsString(FacesContext fc, UIComponent uic, Object o) { 
            return ((Customer) o).getName();
        }
    }
    

    在您的客户服务中:

    @Stateless
    public class CustomerServiceImpl implements CustomerService{
        @Override
        public Customer findByName(String name){
            // assuming you have a name query to fetch by name,
            // otherwise use em.createQuery(...)
            TypedQuery<Customer> query = em.createNamedQuery("Customer.findByName", Customer.class);
            query.setParameter("name", name);
            return query.getSingleResult();
        }
    }
    
  2. 当您的转换器准备就绪时,请调整h:selectOneMenuf:selectItems

最新更新