是否可以通过链联接动态生成CriteriaBuilder查询

时间:2019-02-10 09:35:02

标签: java spring jpa

我写了一个Rest Api。通过指定几种实体和字段组合,用户应该能够以几种方式查询数据库。为了以传统方式实现此目标,我必须为每个可能的查询编写一个GET方法,这是非常繁琐且重复的工作。

我正在尝试在RESTController类中编写一种方法,该方法可读取查询字符串并解析其中的实体和字段 例如

?query=entity=employee,entity=company,employeeId=1,companyName=google

已解析的实体应合并在一起。因此,我使用CriteriaBuilder来生成查询。我编写了一个EntityMapper类,该类读取元模型并生成数据库关系的图形表示。基于此图,我可以找到任何实体之间的路径。

例如,如果我们有几家公司的汽车,而每辆车都可以预订。我们将有三个实体预订,汽车,公司。公司喜欢预订,而不是直接通过汽车实体进行。在这种情况下,路径将是[booking,car,company]。 我正在尝试生成动态查询并按路径顺序加入实体。但是我遇到了以下错误

The method join(SingularAttribute<? super capture#18-of ?,Y>) in the type From<capture#17-of ?,capture#18-of ?> is not applicable for the 
 arguments (SingularAttribute<capture#23-of ?,capture#24-of ?>)

我是否必须使用动态演员表,我们非常感谢您的帮助

@Override
public List<Booking> findByCriteria(List<String> joinEntities, List<SearchCriteria> criteria) {
    Metamodel metamodel = entityManager.getMetamodel();
    List<Predicate> predicates = new ArrayList<Predicate>();
    Map<String, EntityModel<Booking>> entityModels = null;

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<Booking> query = cb.createQuery(Booking.class);
    Root<Booking> root = query.from(Booking.class);

    DynamicQueryHelper queryHelper= new DynamicQueryHelper(entityRelations, entityMapper);
    for(String entity: joinEntities)
    {
        Class<?> entityType= entityMapper.getType(entity);
        List<Integer> entityPath= queryHelper.findPathFromTo(root.getJavaType(), entityType);
        entityType=entityMapper.getType(entityPath.get(1));
        Join<?,?> join= root.join((SingularAttribute<? super Booking, ?>) metamodel.entity(Booking.class).getAttribute(entityType.getSimpleName().toLowerCase()));
        for(int i=2;i<entityPath.size();i++)
        {
            Class<?>attributType=entityMapper.getType(entityPath.get(i));

            join=join.join((SingularAttribute<?, ?>) metamodel.entity(entityType).getAttribute(entityMapper.getType(entityPath.get(i)).getSimpleName().toLowerCase()));

        }

    }

    for (SearchCriteria criterion : criteria) {
        String key = criterion.getKey();

        predicates.add((new BookingSpecification(criterion)).toPredicate(root, query, builder));
    }
    query.where(predicates.toArray(new Predicate[] {}));
    results = entityManager.createQuery(query).getResultList();

    return results;
}

0 个答案:

没有答案