JPA CriteriaBuilder - 如何使用“IN”比较运算符

Posted

技术标签:

【中文标题】JPA CriteriaBuilder - 如何使用“IN”比较运算符【英文标题】:JPA CriteriaBuilder - How to use "IN" comparison operator 【发布时间】:2012-03-08 11:29:39 【问题描述】:

您能帮我如何将以下代码转换为使用标准构建器的“in”运算符吗? 我需要使用“in”使用用户名列表/数组进行过滤。

我也尝试使用 JPA CriteriaBuilder - “in” 方法进行搜索,但找不到好的结果。 因此,如果您能给我这个主题的参考 URL,我也非常感激。谢谢。

这是我的代码:

//usersList is a list of User that I need to put inside IN operator 

CriteriaBuilder builder = getJpaTemplate().getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<ScheduleRequest> criteria = builder.createQuery(ScheduleRequest.class);

Root<ScheduleRequest> scheduleRequest = criteria.from(ScheduleRequest.class);
criteria = criteria.select(scheduleRequest);

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

List<ParameterExpression<String>> usersIdsParamList = new ArrayList<ParameterExpression<String>>();

for (int i = 0; i < usersList.size(); i++) 
ParameterExpression<String> usersIdsParam = builder.parameter(String.class);
params.add(builder.equal(scheduleRequest.get("createdBy"), usersIdsParam) );
usersIdsParamList.add(usersIdsParam);


criteria = criteria.where(params.toArray(new Predicate[0]));

TypedQuery<ScheduleRequest> query = getJpaTemplate().getEntityManagerFactory().createEntityManager().createQuery(criteria);

for (int i = 0; i < usersList.size(); i++) 
query.setParameter(usersIdsParamList.get(i), usersList.get(i).getUsername());


List<ScheduleRequest> scheduleRequestList = query.getResultList();

内部查询字符串转换为下面,所以我没有得到两个用户创建的记录,因为它使用了“AND”。

select generatedAlias0 from ScheduleRequest as generatedAlias0 where ( generatedAlias0.createdBy=:param0 ) and ( generatedAlias0.createdBy=:param1 ) order by generatedAlias0.trackingId asc 

【问题讨论】:

【参考方案1】:

虽然可能不是一个完美的答案,但代码 sn-ps 可能会有所帮助。

public <T> List<T> findListWhereInCondition(Class<T> clazz,
            String conditionColumnName, Serializable... conditionColumnValues) 
        QueryBuilder<T> queryBuilder = new QueryBuilder<T>(clazz);
        addWhereInClause(queryBuilder, conditionColumnName,
                conditionColumnValues);
        queryBuilder.select();
        return queryBuilder.getResultList();

    


private <T> void addWhereInClause(QueryBuilder<T> queryBuilder,
            String conditionColumnName, Serializable... conditionColumnValues) 

        Path<Object> path = queryBuilder.root.get(conditionColumnName);
        In<Object> in = queryBuilder.criteriaBuilder.in(path);
        for (Serializable conditionColumnValue : conditionColumnValues) 
            in.value(conditionColumnValue);
        
        queryBuilder.criteriaQuery.where(in);

    

【讨论】:

非常感谢@gbagga,这件事对我帮助很大!当您使用“CriteriaBuilder”时,上述方法 (exp.in(myList)) 将不起作用。您的方法是使用条件构建器时应该用于“IN”子句的方法。赞一个!【参考方案2】:

如果我理解得很好,您想加入 ScheduleRequestUser 并将 in 子句应用于实体 userName 的属性 User

我需要在这个架构上做一些工作。但是您可以尝试使用这个技巧,它比您发布的代码更具可读性,并且避免了 Join 部分(因为它处理 Criteria 查询之外的 Join 逻辑)。

List<String> myList = new ArrayList<String> ();
for (User u : usersList) 
    myList.add(u.getUsername());

Expression<String> exp = scheduleRequest.get("createdBy");
Predicate predicate = exp.in(myList);
criteria.where(predicate);

为了编写更多类型安全的代码,您还可以通过替换以下行来使用 Metamodel:

Expression<String> exp = scheduleRequest.get("createdBy");

用这个:

Expression<String> exp = scheduleRequest.get(ScheduleRequest_.createdBy);

如果可行,那么您可以尝试将Join 逻辑添加到Criteria Query 中。但是现在我还不能测试,所以我更想看看其他人是否想尝试。

【讨论】:

您好 perissf,感谢您的回复。请问,什么是“ScheduleRequest_”?我如何创建它? 这是一个由您的 JPA 提供者自动生成的元模型类。如果您使用的是 Hibernate,请查看此链接 docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/… 阅读我的伪代码我看到了可能的类型差异。您加入的是 userNames (String) 还是 userIds (Integer / Long)?请让我知道,以便我可以更新我的答案 嗨 perissf,我正在使用字符串用户名。我只是遵循我们没有“_”下划线 bean 的架构,所以我不知道该怎么做。但仍会尝试关注您的链接。谢谢。 谢谢你,它对我有用。虽然我还没有完成类型安全。我不知道如何自动生成类 ScheduleRequest_。非常感谢! :)

以上是关于JPA CriteriaBuilder - 如何使用“IN”比较运算符的主要内容,如果未能解决你的问题,请参考以下文章

如何告诉 JPA CriteriaBuilder 按返回的唯一数据列排序?

如何在 JPA Criteriabuilder Select 语句中执行子查询?

JPA CriteriaBuilder - 如何使用“IN”比较运算符

java-jpa-criteriaBuilder使用入门

真正动态的 JPA CriteriaBuilder

如何使 CriteriaBuilder 加入自定义“开启”条件?