0

Criteria API を使用して奇妙な問題に直面しています。Predicate をクエリに動的に追加したいと考えています。

JPA 2.0 実装として eclipselink-2.4.0.v20120411-r11144 を使用しています。

ご覧のとおり、さまざまな方法を試しましたが、どれもうまくいきませんでした。

それ、どうやったら出来るの?返信ありがとうございます。

@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 に答える