使用带有使用EJB的dropdown元素的java持久性将数据保存到JPA中的外键属性

时间:2017-09-22 12:00:49

标签: java jsp 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 个答案:

答案 0 :(得分:0)

代码错误

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

  1. 缺少可选的referencedColumnName :如注释中所述,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 。请refer to this question for more information

  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>
    
  4. 您转换了错误的值:您的转换器类会转换customerId <-> customer object,而在您的selectOneMenu中,您想要转换customer name <-> customer object

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

  6. 求解

    您需要逐个解决每个问题:

    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