我使用Criteria API面临一个奇怪的问题。我想动态地向查询添加谓词。
我使用eclipselink-2.4.0.v20120411-r11144作为JPA 2.0实现。
正如你所看到的,我已经尝试过各种各样的方法,但都没有。
我该怎么做?谢谢你的回复!
@Repository("mockRepository")
public class MockRepository implements Serializable {
private static final long serialVersionUID = 1L;
@PersistenceContext
private EntityManager em;
@PostConstruct
public void myRequest() {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<MyEntity> query = builder.createQuery(MyEntity.class);
Root<MyEntity> root = query.from(MyEntity.class);
query.where(builder.like(root.get("myAttr").as(String.class), "%foo%")); // SELECT ID, MYATTR, MYSECONDATTR FROM MYENTITY WHERE MYATTR LIKE ? -> Orignal query
//query = addRestriction_1(builder, query, root); // SELECT ID, MYATTR, MYSECONDATTR FROM MYENTITY WHERE ((MYATTR LIKE ? = ?) AND (MYSECONDATTR = ?)) -> query fails
//query = addRestriction_2(builder, query, root); // SELECT ID, MYATTR, MYSECONDATTR FROM MYENTITY WHERE ((MYATTR LIKE ? = ?) AND (MYSECONDATTR = ?)) -> query fails
//query = addRestriction_3(builder, query, root); // SELECT ID, MYATTR, MYSECONDATTR FROM MYENTITY WHERE MYATTR LIKE ? -> where is my second predicate ??
em.createQuery(query).getResultList();
}
private CriteriaQuery<MyEntity> addRestriction_1(CriteriaBuilder builder, CriteriaQuery<MyEntity> query, Root<MyEntity> root) {
query.where(
query.getRestriction(),
builder.equal(root.get("mySecondAttr").as(String.class), "bar")
);
return query;
}
private CriteriaQuery<MyEntity> addRestriction_2(CriteriaBuilder builder, CriteriaQuery<MyEntity> query, Root<MyEntity> root) {
Predicate p = query.getRestriction();
Predicate p1 = builder.equal(root.get("mySecondAttr").as(String.class), "bar");
Predicate p2 = builder.and(p, p1);
query.where(p2);
return query;
}
private CriteriaQuery<MyEntity> addRestriction_3(CriteriaBuilder builder, CriteriaQuery<MyEntity> query, Root<MyEntity> root) {
query.getRestriction().getExpressions().add(
builder.equal(root.get("mySecondAttr").as(String.class), "bar")
);
return query;
}
}
@Entity
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
private String myAttr;
private String mySecondAttr;
public String getMyAttr() {
return myAttr;
}
public void setMyAttr(String myAttr) {
this.myAttr = myAttr;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMySecondAttr() {
return mySecondAttr;
}
public void setMySecondAttr(String mySecondAttr) {
this.mySecondAttr = mySecondAttr;
}
}
答案 0 :(得分:1)
这似乎是getRestriction()中的一个错误,如果它是一个表达式,它返回一个无效的谓词。如果它是一个谓词,它可以工作,所以我的猜测是你将第一个查询改为,
query.where(builder.and(builder.like(root.get("myAttr").as(String.class), "%foo%"), builder.like(root.get("myAttr").as(String.class), "%foo%"));
然后它会起作用。
请记录错误并投票支持。