嗨,我想使用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();
}
}
代码错误
您的代码包含一些错误/缺失点:
-
缺少可选的引用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 }
referencedColumnName
是FOREIGN KEY
并行。以上注释反映了约束:FOREIGN KEY (customerId) REFERENCES customer_table(id)
-
您正在使用 JSF,而不是JSP 。请参阅此问题以获取更多信息。
-
您的
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}
。
-
您正在转换错误的值:转换器类转换
customerId <-> customer object
,而在SelectoneMenu中,您要转换customer name <-> customer object
-
您的转换器类可能缺少
@FacesConverter
注释
解决
您需要一个一个一个地解决每个点:
-
转换器:选择要显示的内容,如果要显示客户名称,则转换器应该看起来像:
@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(); } }
-
当您的转换器准备就绪时,请调整
h:selectOneMenu
和f:selectItems