0

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

1 回答 1

1

这似乎是 getRestriction() 中的一个错误,如果它是一个表达式,它将返回一个无效的谓词。如果它是一个谓词,它虽然有效,所以我的猜测是如果你将你的第一个查询更改为,

query.where(builder.and(builder.like(root.get("myAttr").as(String.class), "%foo%"), builder.like(root.get("myAttr").as(String.class), "%foo%"));

那么它将起作用。

请记录错误并为它投票。

于 2012-05-15T13:38:00.243 回答