我在使用 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;
}
}