JPA2.0 Criteria API:getRestriction()无法正常工作?

时间:2012-05-15 12:22:17

标签: jpa-2.0 eclipselink criteria-api

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

1 个答案:

答案 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%"));

然后它会起作用。

请记录错误并投票支持。