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
state\u table
的表,以三列为例
- 状态id(BigInt)
- 州名称(Varchar)
- 国家/地区id(BigInt)
state\u id
是自动生成的主键,country\u id
是引用country
表主键的外键
此表由其名为
StateTable
的对应实体类映射,并且此表持有的数据显示在PrimefacesDataTable
,…
中
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]);
}