8

私は JSF を初めて使用し、製品のカテゴリを取得するために ah:selectOneMenu を使用するフォームからデータを保存しようとしています。h:selectOneMenu は DB から取り込まれていますが、製品を DB に保存しようとすると、エラーが発生します: 「null コンバーター」の変換エラー設定値「52」。StackOverflow とオンラインのチュートリアルで同様の問題を確認しましたが、まだエラーが発生しています。

これはxhtmlです:

<h:selectOneMenu id="category_fk" value="#{productController.product.category_fk}" 
                                 converter="#{categoryConverter}" title="Category_fk" >
                    <!-- DONE: update below reference to list of available items-->
                    <f:selectItems value="#{productController.categoryList}" var="prodCat"
                                   itemValue="#{prodCat}" itemLabel="#{prodCat.name}"/>
                </h:selectOneMenu>

これは製品コントローラーです。

@Named
@RequestScoped
public class ProductController {

    @EJB
    private ProductEJB productEjb;
    @EJB
    private CategoryEJB categoryEjb;

    private Product product = new Product();
    private List<Product> productList = new ArrayList<Product>();

    private Category category;
    private List<Category> categoryList = new ArrayList<Category>();

    public String doCreateProduct()
    {
        product = productEjb.createProduct(product);
        productList = productEjb.findAllProducts();
        return "listProduct";
    }

    @PostConstruct
    public void init()
    {
        categoryList = categoryEjb.findAllCategory();
        productList = productEjb.findAllProducts();
    }        

    // Getters/Setters and other methods omitted for simplicity

これは、簡単にするために簡略化した EJB です。

   @Stateless
    public class ProductEJB{

        @PersistenceContext(unitName = "luavipuPU")
        private EntityManager em;

        public List<Product> findAllProducts()
        {
            TypedQuery<Product> query = em.createNamedQuery("findAllProducts", Product.class);
            return query.getResultList();
        }

        public Product createProduct(Product product)
        {
            em.persist(product);
            return product;
        }    

    }

これは、簡単にするために単純化された製品エンティティです。

@Entity
@NamedQueries({
    @NamedQuery(name="findAllProducts", query = "SELECT p from Product p")
})
public class Product implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id @GeneratedValue(strategy= GenerationType.AUTO)
    private int product_id;
    private String name;
    private String description;
    protected byte[] imageFile;
    private Float price;
    @Temporal(TemporalType.TIMESTAMP)
    private Date dateAdded;
    @ManyToOne    
    private Category category_fk;
    @ManyToOne
    private SaleDetails saleDetails_fk;

これは私が使用している更新されたコンバーターです:

@ManagedBean
@FacesConverter(value="categoryConverter")
public class CategoryConverter implements Converter{

    @PersistenceContext
    private transient EntityManager em;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        return em.find(Category.class, new Integer(value));
    }

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

        Category category;
        category = (Category) value;
        return String.valueOf(category.getCategory_id());

    }

}

コードは元の問題から更新されており、コードは完全に機能するようになりました。

4

2 に答える 2

11

JSF Converter<h:selectOneMenu/>を作成せずに、コンポーネント (または のいずれか)でカスタム タイプを使用することはできません。JSF にはコンバーターがあり、本質的にカスタムまたはサーバー側の項目/構成を Web ページに適した/人間が読める形式に変換し、クライアント側からの選択をサーバー側に保存することもできます。したがって、エラーメッセージが本質的に伝えているのは、クライアント側から送信された値をオブジェクト/タイプとしてサーバー側に保存するのに十分な意味がないということです<h:selectXXXX/>52Category

したがって、あなたがしなければならないことは、JSFがオブジェクトconverterを理解するのに本質的に役立つ JSFの実装を作成するCategoryことです。

必要な作業の大まかな見積もりは次のとおりです。

  1. Categoryタイプのコンバーターを実装します。

    // You must annotate the converter as a managed bean, if you want to inject
    // anything into it, like your persistence unit for example.
    @ManagedBean(name = "categoryConverterBean") 
    @FacesConverter(value = "categoryConverter")
    public class CategoryConverter implements Converter {
    
        @PersistenceContext(unitName = "luavipuPU")
        // I include this because you will need to 
        // lookup  your entities based on submitted values
        private transient EntityManager em;  
    
        @Override
        public Object getAsObject(FacesContext ctx, UIComponent component,
                String value) {
          // This will return the actual object representation
          // of your Category using the value (in your case 52) 
          // returned from the client side
          return em.find(Category.class, new BigInteger(value)); 
        }
    
        @Override
        public String getAsString(FacesContext fc, UIComponent uic, Object o) {
            //This will return view-friendly output for the dropdown menu
            return ((Category) o).getId().toString(); 
        }
    }
    
  2. 新しいコンバーターを<h:selectOneMenu/>

    <h:selectOneMenu id="category_fk" 
      converter="#{categoryConverterBean}"
      value="#productController.product.category_fk}" 
      title="Category_fk" >
    <!-- DONE: update below reference to list of available items-->
        <f:selectItems value="#{productController.categoryList}" 
          var="prodCat" itemValue="#{prodCat.category_id}" 
          itemLabel="#{prodCat.name}"/>
    </h:selectOneMenu>
    

この名前を使用しているのcategoryConverterBeanは、コンバーターで取得したエンティティ マネージャーのトリックを利用したいからです。それ以外の場合は、コンバーターの注釈に設定した名前を使用していたでしょう。

于 2012-11-02T04:28:50.460 に答える
2

Product.category_fkはCategoryタイプのようで、prodCat.category_idは整数か何かであると思われます...

xhtmlで、selectItemsの値を次のように設定しているようです。itemValue="#{prodCat.category_id}"

selectOneMenuが値を期待する場合value="#{productController.product.category_fk}"

おそらく同じタイプではありません。

于 2012-11-01T18:10:00.957 に答える