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

Jem*_*mru 49 orm hibernate jpa criteria-api jpa-2.0

您能帮我解决一下如何将以下代码转换为使用条件构建器的"in"运算符吗?我需要使用"in"使用列表/数组的用户名进行过滤.

我也尝试使用JPA CriteriaBuilder进行搜索 - "in"方法但是找不到好的结果.如果你能给我这个主题的参考网址,我也非常感谢.谢谢.

这是我的代码:

//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();
Run Code Online (Sandbox Code Playgroud)

内部查询字符串转换为下面,因此我不会获得两个用户创建的记录,因为它使用"AND".

select generatedAlias0 from ScheduleRequest as generatedAlias0 where ( generatedAlias0.createdBy=:param0 ) and ( generatedAlias0.createdBy=:param1 ) order by generatedAlias0.trackingId asc 
Run Code Online (Sandbox Code Playgroud)

per*_*ssf 88

如果我没有理解好了,你想加入ScheduleRequestUser和适用in条款的userName实体的财产User.

我需要对这个架构进行一些研究.但是您可以尝试使用这个技巧,它比您发布的代码更具可读性,并避免使用该Join部分(因为它处理JoinCriteria Query之外的逻辑).

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);
Run Code Online (Sandbox Code Playgroud)

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

Expression<String> exp = scheduleRequest.get("createdBy");
Run Code Online (Sandbox Code Playgroud)

有了这个:

Expression<String> exp = scheduleRequest.get(ScheduleRequest_.createdBy);
Run Code Online (Sandbox Code Playgroud)

如果它有效,那么您可以尝试将Join逻辑添加到Criteria Query.但是现在我无法测试它,所以我更愿意看看别人是否想尝试一下.

  • 它是由JPA提供程序自动生成的Metamodel类.如果您使用的是Hibernate,请查看此链接http://docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/html_single/ (2认同)

bab*_*ira 15

虽然代码片段可能有所帮助,但不是一个完美的答案.

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

    }
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢@gbagga,这件事对我帮助很大!当您使用“ CriteriaBuilder”时,上述方法(exp.in(myList))将不起作用。您的方法是使用criteriaBuilder时应用于“ IN”子句的方法。荣誉! (2认同)