Java 在基于LazyDataModel的排序/筛选字段创建JPA条件查询时,去掉if-else梯形图

Java 在基于LazyDataModel的排序/筛选字段创建JPA条件查询时,去掉if-else梯形图,java,jsf-2,primefaces,jpa-2.0,criteria-api,Java,Jsf 2,Primefaces,Jpa 2.0,Criteria Api,我在用 JPA2.0 莫哈拉2.1.9 JSF组件库,Primefaces 3.5 MySQL 5.6.11 我在MySQL数据库中有一个名为state\u table的表,以三列为例 状态id(BigInt) 州名称(Varchar) 国家/地区id(BigInt) state\u id是自动生成的主键,country\u id是引用country表主键的外键 此表由其名为StateTable的对应实体类映射,并且此表持有的数据显示在PrimefacesDataTable,…中 Da

我在用

  • JPA2.0
  • 莫哈拉2.1.9
  • JSF组件库,Primefaces 3.5
  • MySQL 5.6.11
我在MySQL数据库中有一个名为
state\u table
的表,以三列为例

  • 状态id(BigInt)
  • 州名称(Varchar)
  • 国家/地区id(BigInt)
state\u id
是自动生成的主键,
country\u id
是引用
country
表主键的外键


此表由其名为
StateTable
的对应实体类映射,并且此表持有的数据显示在Primefaces
DataTable

DataTable
列标题包含一个可单击的排序区域,
对于具有排序方向的每一列,单击该区域时,将呈现一个表示排序顺序的字符串(升序或降序),以及一个用于筛选(搜索)的文本框其中用户为每列输入一个搜索项


所以最终,我在JSF托管bean中得到的是一个类型为
java.util.List
的列表,表示用户希望的
DataTable
列的排序顺序

以及
java.util.Map
类型的映射,该映射将搜索列名表示为键,并将相应列的搜索项表示为值(用户在
DataTable
的每列的列标题上的文本框中输入搜索项)


简而言之,我使用
List
进行排序,使用
Map
进行过滤/搜索

我在其中一个DAO中获得排序和筛选后的行列表的代码如下所示

@Override
@SuppressWarnings("unchecked")
public List<StateTable> getList(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, String>filters)
{
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<StateTable> criteriaQuery = criteriaBuilder.createQuery(StateTable.class);
    Metamodel metamodel=entityManager.getMetamodel();
    EntityType<StateTable> entityType = metamodel.entity(StateTable.class);
    Root<StateTable>root=criteriaQuery.from(entityType);
    Join<StateTable, Country> join = null;

    //Sorting

    List<Order> orders=new ArrayList<Order>();

    if(multiSortMeta!=null&&!multiSortMeta.isEmpty())
    {
        for(SortMeta sortMeta:multiSortMeta)
        {
            if(sortMeta.getSortField().equalsIgnoreCase("stateId"))
            {
                orders.add(sortMeta.getSortOrder().equals(SortOrder.ASCENDING)?criteriaBuilder.asc(root.get(StateTable_.stateId)):criteriaBuilder.desc(root.get(StateTable_.stateId)));
            }
            else if(sortMeta.getSortField().equalsIgnoreCase("stateName"))
            {
                orders.add(sortMeta.getSortOrder().equals(SortOrder.ASCENDING)?criteriaBuilder.asc(root.get(StateTable_.stateName)):criteriaBuilder.desc(root.get(StateTable_.stateName)));
            }
            else if(sortMeta.getSortField().equalsIgnoreCase("country.countryName")) // Yes, Primefaces DataTable renders this ugly name in case of a nested property representing a foreign key relationship.
            {
                join = root.join(StateTable_.countryId, JoinType.INNER);
                orders.add(sortMeta.getSortOrder().equals(SortOrder.ASCENDING)?criteriaBuilder.asc(join.get(Country_.countryName)):criteriaBuilder.desc(join.get(Country_.countryName)));
            }
        }
    }

    //Filtering/searching

    List<Predicate>predicates=new ArrayList<Predicate>();

    if(filters!=null&&!filters.isEmpty())
    {
        for(Entry<String, String>entry:filters.entrySet())
        {
            if(entry.getKey().equalsIgnoreCase("stateId"))
            {
                predicates.add(criteriaBuilder.equal(root.get(StateTable_.stateId), Long.parseLong(entry.getValue())));
            }
            else if(entry.getKey().equalsIgnoreCase("stateName"))
            {
                predicates.add(criteriaBuilder.like(root.get(StateTable_.stateName), "%"+entry.getValue()+"%"));
            }
            else if(entry.getKey().equalsIgnoreCase("country.countryName"))// Yes, Primefaces DataTable renders this ugly name in case of a nested property representing a foreign key relationship.
            {
                if(join==null)
                {
                    join = root.join(StateTable_.countryId, JoinType.INNER);
                }
                predicates.add(criteriaBuilder.like(join.get(Country_.countryName), "%"+entry.getValue()+"%"));
            }
        }
    }

    if(predicates!=null&&!predicates.isEmpty())
    {
        criteriaQuery.where(predicates.toArray(new Predicate[0]));
    }

    if(orders!=null&&!orders.isEmpty())
    {
        criteriaQuery.orderBy(orders);
    }
    else
    {
        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(StateTable_.stateId)));
    }
    TypedQuery<StateTable> typedQuery = entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize);
    return typedQuery.getResultList();        
}
@覆盖
@抑制警告(“未选中”)
public List getList(int-first、int-pageSize、List-multiSortMeta、Mapfilters)
{
CriteriaBuilder CriteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery CriteriaQuery=criteriaBuilder.createQuery(StateTable.class);
Metamodel Metamodel=entityManager.getMetamodel();
EntityType EntityType=元模型.entity(StateTable.class);
Rootroot=criteriaQuery.from(entityType);
Join=null;
//分类
列表顺序=新的ArrayList();
if(multiSortMeta!=null&&!multiSortMeta.isEmpty())
{
for(SortMeta SortMeta:MultiportMeta)
{
if(sortMeta.getSortField().equalsIgnoreCase(“stateId”))
{
orders.add(sortMeta.getSortOrder().equals(SortOrder.升序)?criteriaBuilder.asc(root.get(StateTable.stateId)):criteriaBuilder.desc(root.get(StateTable.stateId));
}
else if(sortMeta.getSortField().equalsIgnoreCase(“stateName”))
{
orders.add(sortMeta.getSortOrder().equals(SortOrder.升序)?criteriaBuilder.asc(root.get(StateTable\uuu.stateName)):criteriaBuilder.desc(root.get(StateTable\uu.stateName));
}
else if(sortMeta.getSortField().equalsIgnoreCase(“country.countryName”)//是,Primefaces DataTable在表示外键关系的嵌套属性的情况下呈现这个丑陋的名称。
{
join=root.join(StateTable.countryId,JoinType.INNER);
orders.add(sortMeta.getSortOrder().equals(SortOrder.升序)?criteriaBuilder.asc(join.get(Country.countryName)):criteriaBuilder.desc(join.get(Country.countryName));
}
}
}
//筛选/搜索
Listpredicates=newArrayList();
if(filters!=null&!filters.isEmpty())
{
for(Entryentry:filters.entrySet())
{
if(entry.getKey().equalsIgnoreCase(“stateId”))
{
add(criteriaBuilder.equal(root.get(StateTable.stateId)、Long.parseLong(entry.getValue()));
}
else if(entry.getKey().equalsIgnoreCase(“stateName”))
{
add(criteriaBuilder.like(root.get(StateTable.stateName),“%”加上entry.getValue()+“%”);
}
else if(entry.getKey().equalsIgnoreCase(“country.countryName”)//是,Primefaces DataTable在表示外键关系的嵌套属性的情况下呈现这个丑陋的名称。
{
if(join==null)
{
join=root.join(StateTable.countryId,JoinType.INNER);
}
add(criteriaBuilder.like(join.get(Country\uu.countryName),“%”+entry.getValue()+“%”);
}
}
}
if(谓词!=null&&!谓词.isEmpty())
{
criteriaQuery.where(谓词.toArray(新谓词[0]);
}
if(orders!=null&!orders.isEmpty())
{
criteriaQuery.orderBy(订单);
}
其他的
{
orderBy(criteriaBuilder.desc(root.get(StateTable.stateId));
}
TypedQuery TypedQuery=entityManager.createQuery(criteriaQuery).setFirstResult(first).setMaxResults(pageSize);
返回typedQuery.getResultList();
}
这与预期的一样有效,但可以注意到,
foreach
循环中的
if-else-if
梯形图可以包含许多条件检查,因为数据库表中的列数增加了

每列都需要对排序和搜索进行条件检查。是否有一种有效的方法来消除这些条件检查,从而最终消除或至少最小化此
if-else-if
ladder


注意:对于国家,我在
countryName
(可在父表
country
中找到)上进行排序和搜索,而不是
countryId
。因此,在本例中,我使用了
Join

如果您放弃使用
SingularAttribute
值,并确保调用方在sort/filter f中使用所需的列名称调用该方法
/**
 * @throws NullPointerException When <code>multiSortMeta</code> or <code>filters</code> argument is null.
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public List<?> getList(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, String> filters) {
    // ...

    Root<StateTable> root = criteriaQuery.from(entityType);
    Join<StateTable, Country> join = root.join(StateTable_.countryId, JoinType.INNER);

    List<Order> orders = new ArrayList<Order>();

    for (SortMeta sortMeta : multiSortMeta) {
        String[] sortField = sortMeta.getSortField().split("\\.", 2);
        Path<Object> path = sortField.length == 1 ? root.get(sortField[0]) : join.get(sortField[1]);
        orders.add(sortMeta.getSortOrder() == SortOrder.ASCENDING 
            ? criteriaBuilder.asc(path) 
            : criteriaBuilder.desc(path));
    }

    List<Predicate>predicates = new ArrayList<Predicate>();

    for (Entry<String, String> filter : filters.entrySet()) {
        String[] filterField = filter.getKey().split("\\.", 2);
        Path path = filterField.length == 1 ? root.get(filterField[0]): join.get(filterField[1]);
        predicates.add(filter.getValue().matches("[0-9]+") 
            ? criteriaBuilder.equal(path, Long.valueOf(filter.getValue()))
            : criteriaBuilder.like(path, "%" + filter.getValue() + "%"));
    }

    // ...
}
@SuppressWarnings("rawtypes")
private static Path<?> getPath(String field, Root root, Join join) {
    String[] fields = field.split("\\.", 2);
    return fields.length == 1 ? root.get(fields[0]): join.get(fields[1]);
}