tanapoln
tanapoln

Reputation: 529

Spring Data JPA with Querydsl -- filter by value inside array from URL

Assumed that I have 2 entity. The first entity is parent of the second entity with one-to-many relation.

class Item {
    String name;
    Integer price;
}

class Order {
    List<Item> items;
    String customerName;
}

And I have repository defined like this:

interface OrderRepository extends JpaRepository<Order, Long>, QueryDslPredicateExecutor<Order> {
}

After that, I have a controller that automatically bind parameter to predicate like this:

@RestController
@RequestMapping(path = "/orders")
class OrderController {
    @RequestMapping(method = RequestMethod.GET)
    List<Order> list(@QuerydslPredicate Predicate predicate) {
        return orderRepository.findAll(predicate);
    }   
}

So, I can query order from repository with a specific filter like this: curl -XGET http://localhost/orders?customerName=John

The problem is that I cannot filter value inside a list. I also try http://localhost/orders?items.name=Bag but got NullPointerException

java.lang.NullPointerException
    at org.springframework.util.ReflectionUtils.getField(ReflectionUtils.java:143) ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.reifyPath(QuerydslPredicateBuilder.java:185) ~[spring-data-commons-1.11.4.RELEASE.jar:?]
    ...

So, the questions is, how can I filter value inside list with Spring JPA and Querydsl.

Note: I use spring boot 1.3.4 with querydsl-jpa 3.7.4

Thanks.

Upvotes: 0

Views: 4282

Answers (1)

Oliver Drotbohm
Oliver Drotbohm

Reputation: 83121

That's a two-fold bug actually. Our translation to dot-names is broken for that particular scenario, even if you defined a custom binding like this:

bindings.bind(user.addresses.any().street).as("alias").first(…);

which would be a solution to work around our failure to handle the collection path traversal out of the box.

I've filed DATACMNS-883 for you to solve both problems:

  1. Collection path traversals should automatically result in the call to any() added during path reification.
  2. Manually declared (and aliased) path bindings including an any() traversal should work properly.

Fix is available (try the latest snapshots) and scheduled for both the Ingalls milestone and a Hopper and Gosling service release.

Upvotes: 1

Related Questions