JSF中的访问器/获取器方法内部的业务逻辑 [英] Business logic inside an accessor / getter method in JSF

查看:109
本文介绍了JSF中的访问器/获取器方法内部的业务逻辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在MySQL数据库中有三个表.

I have three tables in MySQL database.

  • 类别(此问题排除在外)
  • sub_category
  • 产品

这些表之间的关系很直观-按它们出现的顺序一对多.

The relationship between these tables is intuitive - one-to-many in the order in which they appear.

我正在使用 遍历SubCategoryList<SubCategory>的列表c2> 如下.

I'm iterating through a list of SubCategory, List<SubCategory> using <p:dataGrid> as follows.

<p:dataGrid var="row" value="#{featuredProductManagedBean}" rows="4" first="0" columns="1" rowIndexVar="rowIndex" paginator="true" paginatorAlwaysVisible="false" pageLinks="10" lazy="true" rowsPerPageTemplate="5,10,15">
    <h:panelGrid columns="1" style="width:100%;">
        <p:carousel value="#{featuredProductManagedBean.getProducts(row.subCatId)}" var="prodRow" numVisible="4" pageLinks="5" headerText="#{row.subCatName}" style="text-align: left;">

            <!--Display product image in <p:graphicImage>-->

        </p:carousel>
        <h:outputLink rendered="#{featuredProductManagedBean.count gt 4}" value="xxx">View More</h:outputLink>
    </h:panelGrid>

    <p:ajax event="page" onstart="PF('blockDataPanelUIWidget').block()" oncomplete="PF('blockDataPanelUIWidget').unblock()"/>
</p:dataGrid>

有一个与 </p:carousel> 的value属性关联的参数化吸气方法. a> featuredProductManagedBean.getProducts(row.subCatId).

多次调用该方法,导致多次调用昂贵的业务服务.

The method is called several times causing the expensive business service(s) to be invoked several times.

托管bean:

@ManagedBean
@ViewScoped
public final class FeaturedProductManagedBean extends LazyDataModel<SubCategory> implements Serializable
{
    @EJB
    private final FeaturedProductBeanLocal service=null;
    private Product selectedProduct;  //Getter and setter.
    private Long count;               //Getter and setter.  
    private static final long serialVersionUID = 1L;

    public FeaturedProductManagedBean() {}

    public List<Product>getProducts(Long subCatId)
    {
        List<Product>products=null;

        if(FacesContext.getCurrentInstance().getCurrentPhaseId().getOrdinal()==6)
        {
            setCount(service.countProducts(subCatId));
            products=service.getProductList(subCatId);
        }

        return products;
    }

    @Override
    public List<SubCategory> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters)
    {
        int rowCount = service.rowCount().intValue();
        setRowCount(rowCount);

        if(pageSize<=0)
        {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_FATAL, Utility.getMessage("faces.message.error"), Utility.getMessage("pageSize.error.message"));
            FacesContext.getCurrentInstance().addMessage(null, message);
            return Collections.emptyList();
        }
        else if(first>=pageSize&&rowCount<=Utility.currentPage(first, pageSize)*pageSize-pageSize) {
            first-=pageSize;
        }

        setPageSize(pageSize);
        return service.getList(first, pageSize);
    }
}

在这里不能使用@PostConstruct非延迟加载.目前,我已经进行了条件检查if(FacesContext.getCurrentInstance().getCurrentPhaseId().getOrdinal()==6),以防止多次调用服务方法.此条件检查是否执行正确的操作?有副作用吗?

Neither @PostConstruct not lazy loading can be used here. Currently I have put a conditional check if(FacesContext.getCurrentInstance().getCurrentPhaseId().getOrdinal()==6) to prevent the service methods from being called multiple times. Does this conditional check perform the right thing? Does it have some side effects?

答案维护Map,但是维护大型数据源的Map则很昂贵.

This answer maintains a Map but maintaining a Map for large data sources is expensive.

是否存在防止此类业务逻辑多次执行的精确方法?

Is there a precise way to prevent such business logic from being executed multiple times?

推荐答案

我建议将当前加载的subCategory的产品存储在Map中,紧接着是<p:dataGrid>的惰性模型加载它们之后. Map永远不会增长太多,因为您每次调用load方法时都会将其清空:

I suggest to store the products of the currently loaded subCategory in a Map, just after they are loaded by the lazy model of <p:dataGrid>. The Map will never grow too much because you'll empty it at each invocation of the load method:

@ManagedBean
@ViewScoped
public final class FeaturedProductManagedBean extends LazyDataModel<SubCategory> implements Serializable
{
    @EJB
    private final FeaturedProductBeanLocal service=null;
    private Product selectedProduct;  //Getter and setter.
    private Long count;               //Getter and setter.  
    private Map<Long, Product> productsBySubCategory = new HashMap<>(); //Getter only.
    private static final long serialVersionUID = 1L;

    @Override
    public List<SubCategory> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters)
    {
        int rowCount = service.rowCount().intValue();
        setRowCount(rowCount);

        List<SubCategory> subCategories = service.getList(first, pageSize);
        productsBySubCategory.clear();
        for (SubCategory sc : subCategories) 
        {
            productsBySubCategory.put(sc.getSubCatId(), service.getProductList(sc.getSubCatId());
        }
        return subCategories;
    }
}

然后直接从EL中访问Map:

And access directly the Map from EL:

<p:carousel value="#{featuredProductManagedBean.productsBySubCategory[row.subCatId]}" />

请注意,您不需要检查页面边界并设置页面大小的所有样板.

Note that you don't need all that boilerplate that checks page boundaries and sets pagesize.

这篇关于JSF中的访问器/获取器方法内部的业务逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆