2014-04-01 31 views
1

我在MySQL数据库中有三个表。JSF中访问器/ getter方法内的业务逻辑

  • 类别(从这个问题除外)
  • sub_category
  • 产物

这些表之间的关系是直观的 - 一个一对多以它们出现的顺序。


我使用<p:dataGrid>如下迭代通过SubCategory列表,List<SubCategory>

<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>featuredProductManagedBean.getProducts(row.subCatId)值属性相关联的参数获取方法。

该方法被多次调用导致昂贵的业务服务被多次调用。

管理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)以防止多次调用服务方法。这个条件检查是否执行正确的事情?它有一些副作用吗?

This答案维持Map,但对于大型数据源维护Map是昂贵的。

是否有一种精确的方法来防止这种业务逻辑被多次执行?

+1

为了防止多次执行业务逻辑,您应将其移出getter并置于PostConstruct方法中。目前还不清楚你为什么说你不能。 – perissf

+0

单击commandButton时可能出现多次[Primefaces dataTable调用方法。为什么?](http://stackoverflow.com/questions/22662276/primefaces-datatable-call-method-multiple-times-when-click-commandbutton-why) –

+0

因为它大概不可能使用[criteria/JPQL]( http://stackoverflow.com/q/22523074/1391249),@perissf – Tiny

回答

1

我建议将当前加载的subCategory的产品存储在Map中,紧接着它们由<p:dataGrid>的懒惰模型加载后。

@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; 
    } 
} 

,并获得直接的Map从EL:

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

注意,你并不需要在地图绝不会在load方法的每次调用增长太多,因为你会清空所有那些检查页面边界并设置页面大小的样板。

+0

完成!非常感谢:) – Tiny

+1

欢迎,这是一种乐趣 – perissf