0

在您从 SELECT 中选择 ProductView 后,我有一个带有 ProductViews 列表(作为 SELECT)的检票口面板
按类别列出的产品列表
,它通过 ProductView 的 id 从数据库中加载产品到详细信息表单中。您可以修改产品实体,完成后可以保存。
详细信息表
保存后我尝试刷新 SELECT 列表以更新其数据,但它不起作用(我的意思是,例如,SELECT 在重命名后包含产品的旧名称,但是当我选择相同的 ProductView 时,它会将实体重新加载到再次详细信息表格,当然新数据出现在数据库中)我不想再次重新加载产品列表,我想从内存中解决它。这是我的来源:

产品视图:

@Entity
@Table(name = "product")
@XmlRootElement
public class ProductView implements Serializable{

        private static final long serialVersionUID = 1L;
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Basic(optional = false)
        @Column(name = "id")
        private Long id;
        @Column(name = "name")
        private String name;
        @Enumerated(EnumType.ORDINAL)
        @Column(name = "category")
        private Category category;

        public ProductView() {
        }
        public ProductView(Long id) {
            this.id = id;
        }
        public ProductView(Product product) {
            this.id = product.getId();
            this.name = product.getName();
            this.category = product.getCategory();
        }
        // + getters & setters
    }

产品:

@Entity
@Table(name = "product")
@XmlRootElement
public class Product implements Serializable {
    // same as ProductView but more data, objects, connections, etc
}

和带有评论的检票口面板

private Product product;
private ProductView productView;
private List<ProductView> productViews;

private Form productForm;
private Select categorySelectComponent;
private WebMarkupContainer contentContainer;

public ProductPanel(String id) {
    super(id);
    setOutputMarkupId(true);

    add(contentContainer = new WebMarkupContainer("contentContainer")); // container DIV
    contentContainer.setOutputMarkupId(true); // refreshable
    contentContainer.add(productForm = new Form("productForm")); // details FORM
    contentContainer.add(categorySelectComponent = new Select("categorySelectComponent", new PropertyModel<ProductView>(this, "productView"))); // item SELECT

    categorySelectComponent.add( new SelectOptions<ProductView>( // first category
            "oneCategory",
            new PropertyModel<List<ProductView>>(this, "oneProducts"), // see getOneProducts(); list of productviews
            new IOptionRenderer<ProductView>() {
                @Override
                public String getDisplayValue(ProductView p) {
                    return p.getName();
                }
                @Override
                public IModel<ProductView> getModel(ProductView p) {
                    return new Model<ProductView>(p);
                }
            }));
    categorySelectComponent.add( new SelectOptions<ProductView>( // second category
            "twoCategory",
            new PropertyModel<List<ProductView>>(this, "twoProducts"), // see getTwoProducts();
            new IOptionRenderer<ProductView>() {
                @Override
                public String getDisplayValue(ProductView p) {
                    return p.getName();
                }
                @Override
                public IModel<ProductView> getModel(ProductView p) {
                    return new Model<ProductView>(p);
                }
            }));
    categorySelectComponent.add( new SelectOptions<ProductView>( // third category
            "threeCategory",
            new PropertyModel<List<ProductView>>(this, "threeProducts"), // see getThreeProducts();
            new IOptionRenderer<ProductView>() {
                @Override
                public String getDisplayValue(ProductView p) {
                    return p.getName();
                }
                @Override
                public IModel<ProductView> getModel(ProductView p) {
                    return new Model<ProductView>(p);
                }
            }));

    categorySelectComponent.add(new OnChangeAjaxBehavior() { // update form after choose entity
        @Override
        protected void onUpdate(final AjaxRequestTarget art) {
            product = getProductFacade().find( productView.getId() );
            updatePanel(art);
        }
    });

    productForm.add(
        // some details component (textfields, radios, links, etc) to edit Product
    );
    productForm.add(new AjaxSubmitLink("formSubmitLink") { // save entity
        @Override
        protected void onSubmit(AjaxRequestTarget art, Form<?> form) {
            super.onSubmit(art, form); // i don't know it is necessary at all
            getProductFacade().edit( product );
            updateProductViewInCategoryMap(art); // important method
            //art.add(contentContainer); //it is in update method
        }
    });
}

面板内的更多方法

private Map<Category, List<ProductView>> categoryMap; // all product by categories
public void initCategoryMap() {
    categoryMap = new EnumMap<Category, List<ProductView>>(ProductView.class);
    categoryMap.put( Category.ONE,  new ArrayList<ProductView>() );
    categoryMap.put( Category.TWO,  new ArrayList<ProductView>() );
    categoryMap.put( Category.THREE,  new ArrayList<ProductView>() );

    for (ProductView view : getProductViews()) {
        categoryMap.get(view.getCategory()).add(view);
    }
}

//***** Get Products By Categories *******

final public List<ProductView> getOneProducts(){
    if (categoryMap == null){
        initCategoryMap();
    }
    return categoryMap.get( Category.ONE );
}

final public List<ProductView> getTwoCategory(){
    if (categoryMap == null){
        initCategoryMap();
    }
    return categoryMap.get( Category.TWO );
}

final public List<ProductView> getThreeProducts(){
    if (categoryMap == null){
        initCategoryMap();
    }
    return categoryMap.get( Category.THREE );
}

// **************************************

public List<ProductView> getProductViews() { // Get All Product
    if (productViews == null) {
        productViews = getProductFacade().findAllProductAsView();
    }
    return productViews;
}

private void updatePanel(AjaxRequestTarget art) { // refresh panel
    art.add(ProductPanel.this);
}

private void updateProductViewInCategoryMap(AjaxRequestTarget art) { // change Product in map after save (call from onSubmit method of AjaxSubmitLink)
    for(Map.Entry<Category, List<ProductView>> entry : categoryMap.entrySet()){ // search category contains entity
        if (entry.getValue().contains( productView )){
            entry.getValue().remove( productView ); // remove entity from category
            break;
        }
    }
    productView = new ProductView( product ); // new productview by modified product
    categoryMap.get( productView.getCategory() ).add( productView ); // add entity to it's category's list 
    art.add(contentContainer);
}

和 HTML:

<select class="categorySelect" wicket:id="categorySelectComponent">
    <optgroup label="Category One">
        <wicket:container wicket:id="oneCategory">
                <option wicket:id="option"></option>
             </wicket:container>
    </optgroup>
    <optgroup label="Category Two">
        <wicket:container wicket:id="twoCategory">
                    <option wicket:id="option"></option>
            </wicket:container>
    </optgroup>
    <optgroup label="Category Three">
        <wicket:container wicket:id="threeCategory">
                <option wicket:id="option"></option>
            </wicket:container>
    </optgroup>
</select>

任何想法?

4

2 回答 2

1

更新productViews保存更改或使用LoadableDetachableModel而不是PropertyModelincategorySelectComponent怎么样?

这里:

new Select("categorySelectComponent", new PropertyModel<ProductView>(this, "productView")
于 2013-05-04T16:27:27.843 回答
1

在所有 SelectOptions 上调用 #setRecreateChoices(true)。

于 2013-05-05T18:43:36.670 回答