问题描述
我正在测试一个JPA存储库。这里是我的客户端/测试代码:
@Test
public void testFindBoitesByMultiFieldWithIdentifiantSet(){
BoiteDataOnDemand dod = new BoiteDataOnDemand();
Boite boite = dod.getSpecificBoite(0);
boite.setIdentifiant(theIdentifiant);
boiteRepository.save(boite);
assertEquals(10,Boite.countBoites());
BoiteQueryInfo boiteQueryInfo = new BoiteQueryInfo();
boiteQueryInfo.setIdentifiant(theIdentifiant);
列表< Boite> boites = boiteRepository.findBoitesByMultiField(boiteQueryInfo,1,5,identifiant,desc);
assertEquals(1,boites.size());
}
以下是储存库方法:
@Override
public List< Boite> findBoitesByMultiField(BoiteQueryInfo boiteQueryInfo,Integer firstResult_,Integer maxResults_,String sort_,String order_){
log.debug(findBoitesByMultiField);
final String identifiant = boiteQueryInfo.getIdentifiant();
final日期dateOuvertureFrom = boiteQueryInfo.getDateOuvertureFrom();
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery< Boite> c = criteriaBuilder.createQuery(Boite.class);
Root< Boite> boite = c.from(Boite.class);
列表<谓词> criteria = new ArrayList< Predicate>();
...
if(identifiant!= null&&!identifiant.trim()。equals()){
ParameterExpression< String> parameter = criteriaBuilder.parameter(String.class,identifiant);
谓词条件= criteriaBuilder.like(boite。< String> get(identifiant),parameter);
criteria.add(condition);
}
if(dateOuvertureFrom!= null&& dateOuvertureTo!= null){
ParameterExpression< Date> parameterDateOuvertureFrom = criteriaBuilder.parameter(Date.class,dateOuvertureFrom);
ParameterExpression< Date> parameterDateOuvertureTo = criteriaBuilder.parameter(Date.class,dateOuvertureTo);
谓词条件= criteriaBuilder.between(boite。< Date> get(dateOuverture),parameterDateOuvertureFrom,parameterDateOuvertureTo);
criteria.add(condition);
} else if(dateOuvertureFrom!= null){
ParameterExpression< Date>参数= criteriaBuilder.parameter(Date.class,dateOuvertureFrom);
谓词条件= criteriaBuilder.greaterThanOrEqualTo(boite。< Date> get(dateOuverture),parameter);
criteria.add(condition);
} else if(dateOuvertureTo!= null){
ParameterExpression< Date>参数= criteriaBuilder.parameter(Date.class,dateOuvertureTo);
谓词条件= criteriaBuilder.lessThanOrEqualTo(boite。< Date> get(dateOuverture),parameter);
criteria.add(condition);
$ b ...
if(order.equalsIgnoreCase(desc)){
c.orderBy(criteriaBuilder.desc(boite.get(sort) ));
} else {
c.orderBy(criteriaBuilder.asc(boite.get(sort)));
}
for(Predicate predicate:criteria){
c.where(criteriaBuilder.and(predicate));
}
TypedQuery< Boite> q = em.createQuery(c);如果(识别!=空&&!identifiant.trim()。等于()){
q.setParameter(识别,%+识别+ %); (dateOuvertureFrom!= null&& dateOuvertureTo!= null){
q.setParameter(dateOuvertureFrom,dateOuvertureFrom);
}
if
q.setParameter(dateOuvertureTo,dateOuvertureTo);
} else if(dateOuvertureFrom!= null){
q.setParameter(dateOuvertureFrom,dateOuvertureFrom);
} else if(dateOuvertureTo!= null){
q.setParameter(dateOuvertureTo,dateOuvertureTo);
}
...
return q.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
}
但是,测试总是在 assertEquals(1,boites.size());
指示没有返回结果,即( java.lang.AssertionError:expected:< 1> :
我强烈怀疑这里有些问题:
$ b for(Predicate predicate:criteria){
c.where(criteriaBuilder.and(predicate));
}
但我不确定如何和标准。
任何人都可以提供建议吗?
PS仅供参考, BoiteDataOnDemand
将随机10行插入 boite
表中。
编辑:编辑代码使其缩短。解决方案从您的帖子最后部分的提示开始,我同意你为添加谓词的方式,其中
子句不正确。
我看到两种方法继续:
第一种方式 使用谓词数组
List< Predicate> predicates = new ArrayList< Predicate>(); (key key:keys){
predicates.add(criteriaBuilder.equal(root.get(key),value));
}
c.where(criteriaBuilder.and(predicates.toArray(new Predicate [] {})));
第二种方式
在循环中修改相同的谓词
谓词predicate = criteriaBuilder.conjunction(); (Key key:keys)
{
Predicate newPredicate = criteriaBuilder.equal(root.get(key),value);
predicate = criteriaBuilder.and(predicate,newPredicate);
}
c.where(谓词);
EDITED
再次查看代码示例后,我看到您已经以正确的方式创建了 Predicate
S列表:您已将它称为标准
。你只是以错误的方式使用它们。看到我的第一个例子的最后一行。
编辑2
为了通过使用 PredicateExpressionS
来查看问题是否是由您的情况特别需要的,请尝试暂时删除它们。修改你的第一个标准从
if(identifiant!= null&&!identifiant.trim()。equals( )){
ParameterExpression< String> parameter = criteriaBuilder.parameter(String.class,identifiant);
谓词条件= criteriaBuilder.like(boite。< String> get(identifiant),parameter);
criteria.add(condition);
至
<$ p如果(identify)!= null&&!identifiant.trim()。equals()){
Predicate condition = criteriaBuilder.like(boite.get(identifiant ),%+ identifiant +%);
criteria.add(condition);
}
I am trying to test a JPA repository. Here is my client/test code:
@Test
public void testFindBoitesByMultiFieldWithIdentifiantSet() {
BoiteDataOnDemand dod = new BoiteDataOnDemand();
Boite boite = dod.getSpecificBoite(0);
boite.setIdentifiant("theIdentifiant");
boiteRepository.save(boite);
assertEquals(10, Boite.countBoites());
BoiteQueryInfo boiteQueryInfo = new BoiteQueryInfo();
boiteQueryInfo.setIdentifiant("theIdentifiant");
List<Boite> boites = boiteRepository.findBoitesByMultiField(boiteQueryInfo, 1, 5, "identifiant", "desc");
assertEquals(1, boites.size());
}
Here is the repository method:
@Override
public List<Boite> findBoitesByMultiField(BoiteQueryInfo boiteQueryInfo, Integer firstResult_, Integer maxResults_, String sort_, String order_) {
log.debug("findBoitesByMultiField");
final String identifiant = boiteQueryInfo.getIdentifiant();
final Date dateOuvertureFrom = boiteQueryInfo.getDateOuvertureFrom();
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Boite> c = criteriaBuilder.createQuery(Boite.class);
Root<Boite> boite = c.from(Boite.class);
List<Predicate> criteria = new ArrayList<Predicate>();
...
if (identifiant != null && !identifiant.trim().equals("")) {
ParameterExpression<String> parameter = criteriaBuilder.parameter(String.class, "identifiant");
Predicate condition = criteriaBuilder.like(boite.<String> get("identifiant"), parameter);
criteria.add(condition);
}
if (dateOuvertureFrom != null && dateOuvertureTo != null) {
ParameterExpression<Date> parameterDateOuvertureFrom = criteriaBuilder.parameter(Date.class, "dateOuvertureFrom");
ParameterExpression<Date> parameterDateOuvertureTo = criteriaBuilder.parameter(Date.class, "dateOuvertureTo");
Predicate condition = criteriaBuilder.between(boite.<Date> get("dateOuverture"), parameterDateOuvertureFrom, parameterDateOuvertureTo);
criteria.add(condition);
} else if (dateOuvertureFrom != null) {
ParameterExpression<Date> parameter = criteriaBuilder.parameter(Date.class, "dateOuvertureFrom");
Predicate condition = criteriaBuilder.greaterThanOrEqualTo(boite.<Date> get("dateOuverture"), parameter);
criteria.add(condition);
} else if (dateOuvertureTo != null) {
ParameterExpression<Date> parameter = criteriaBuilder.parameter(Date.class, "dateOuvertureTo");
Predicate condition = criteriaBuilder.lessThanOrEqualTo(boite.<Date> get("dateOuverture"), parameter);
criteria.add(condition);
}
...
if (order.equalsIgnoreCase("desc")) {
c.orderBy(criteriaBuilder.desc(boite.get(sort)));
} else {
c.orderBy(criteriaBuilder.asc(boite.get(sort)));
}
for (Predicate predicate : criteria) {
c.where(criteriaBuilder.and(predicate));
}
TypedQuery<Boite> q = em.createQuery(c);
if (identifiant != null && !identifiant.trim().equals("")) {
q.setParameter("identifiant", "%" + identifiant + "%");
}
if (dateOuvertureFrom != null && dateOuvertureTo != null) {
q.setParameter("dateOuvertureFrom", dateOuvertureFrom);
q.setParameter("dateOuvertureTo", dateOuvertureTo);
} else if (dateOuvertureFrom != null) {
q.setParameter("dateOuvertureFrom", dateOuvertureFrom);
} else if (dateOuvertureTo != null) {
q.setParameter("dateOuvertureTo", dateOuvertureTo);
}
...
return q.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
}
However, the test always fails at assertEquals(1, boites.size());
indicating that no result is returned i.e. (java.lang.AssertionError: expected:<1> but was:<0>
).
I strongly suspect something is wrong here:
for (Predicate predicate : criteria) {
c.where(criteriaBuilder.and(predicate));
}
But I am not sure how to "and" the criteria.
Can anyone please provide advice?
P.S. FYI, BoiteDataOnDemand
inserts random 10 rows into the boite
table.
EDIT: code was edited to make it shorter.
Starting from your hint in the final part of your post, I agree that the way you are adding predicates for the where
clause is not correct.
I see two ways of proceeding:
First way
Using an array of predicates
List<Predicate> predicates = new ArrayList<Predicate>();
for (Key key : keys) {
predicates.add(criteriaBuilder.equal(root.get(key), value));
}
c.where(criteriaBuilder.and(predicates.toArray(new Predicate[] {})));
Second way
Modifying the same predicate in the loop
Predicate predicate = criteriaBuilder.conjunction();
for (Key key : keys) {
Predicate newPredicate = criteriaBuilder.equal(root.get(key), value);
predicate = criteriaBuilder.and(predicate, newPredicate);
}
c.where(predicate);
EDITED
After looking again your code sample, I see that you have already created in the correct way a list of Predicate
S: you have called it criteria
. You are only using them in the wrong way. See the last line of my first example.
EDIT 2
In order to see if the problem is generated by the use of PredicateExpressionS
, that are not specifically needed in your case, try to temporarily remove them. Modify your first criteria from
if (identifiant != null && !identifiant.trim().equals("")) {
ParameterExpression<String> parameter = criteriaBuilder.parameter(String.class, "identifiant");
Predicate condition = criteriaBuilder.like(boite.<String> get("identifiant"), parameter);
criteria.add(condition);
}
to
if (identifiant != null && !identifiant.trim().equals("")) {
Predicate condition = criteriaBuilder.like(boite.get("identifiant"), "%" + identifiant + "%");
criteria.add(condition);
}
这篇关于正确使用JPA标准API,Predicates和CriteriaQuery的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!