2

I would like to use a parameter expression as part of an in clause. I would like to query for a list of Foos that have a Bar that is in a set of Bars. Is this possible?

Foo
    // Join, ManyToOne
    Bar getBar()

Query
    ParameterExpression<???> barParameter;

    void setup() {
        CriteriaBuilder builder = ...
        CriteriaQuery<Foo> criteria = ...
        Root<Bar> root = ...

        barParameter = builder.parameter(???);

        criteria.where(
            builder.in(root.get(Foo_.bar)).value(barParameter)
        );
    }

    List<Foo> query(Set<Bar> bars) {
        TypedQuery<Foo> query = createQuery();
        query.setParameter(barParameter, bars);
        return query.getResultList();
    }
Craig Swing
  • 8,152
  • 2
  • 30
  • 43
  • Maybe this [link](http://stackoverflow.com/a/11349052/870122) can be helpful: it's not about `ParameterExpression`S, but could be a starting point... – perissf Aug 07 '12 at 12:46
  • Everything I had found (including your link) has the actual data for the in clause at the time of creating the CriteriaQuery. I have been using a pattern where the CriteriaQuery is built once and the actual parameters are set using parameter expressions. I was just hoping there was something simple I was overlooking to use a ParameterExpression. – Craig Swing Aug 07 '12 at 15:19

1 Answers1

9

With in expressions you can only use primitive comparison types, so you need to make a join and compare a field of a primitive type (here I have used Integer id):

Root<Foo> foo = cq.from(Foo.class);
Join<Foo, Bar> bar = foo.join(Foo_.bar);
ParameterExpression<Collection> bars = cb.parameter(Collection.class);
cq.where(bar.get(Bar_.id).in(bars));
TypedQuery<Foo> tq = em.createQuery(cq);
Collection<Integer> barsParameter = new ArrayList<Integer> ();
barsParameter.add(1);
List<Foo> resultList = tq.setParameter(bars, barsParameter).getResultList();
perissf
  • 15,979
  • 14
  • 80
  • 117