Get rid of the if-else ladder when creating a JPA criteria request based on sort / filter fields in LazyDataModel

I use

  • JPA 2.0
  • Mojarra 2.1.9
  • JSF Component Library, Primfaces 3.5.
  • MySQL 5.6.11

I have a table in a MySQL database with a name state_tablewith three columns as an example.

  • state_id (BigInt)
  • state_name (Varchar)
  • country_id (BigInt)

state_idis the automatically generated primary key, and country_idis the foreign key that refers to the primary key of the table country.


This table shows the corresponding entity class with the name StateTable, and the data stored in this table are displayed in Primefaces files DataTable, <p:dataTable>...</p:dataTable>.

DataTable <div> , , ASCENDING DESCENDING, , rendered (), .


, , JSF, bean - List of type java.util.List<org.primefaces.model.SortMeta>, DataTable, .

java.util.Map<java.lang.String, java.lang.String>, ( DataTable).


, List<SortMeta> Map<String, String> /.

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();        
}

, , , , if-else if foreach .

, . , if-else if?

P.S. countryName ( country), countryId. , Join, .

+3
1

SingularAttribute , , , / if/else , ( /).

, equalsIgnoreCase() if-else . , , , , .

:

/**
 * @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() + "%"));
    }

    // ...
}

, , null , . , for , . , CriteriaBuilder#equal(), , like(). , , , .

Path :

@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]);
}
+5

Source: https://habr.com/ru/post/1621613/


All Articles