Reputation: 748
I have the following (simplified) entity structure:
public class Animal {
private long id;
private int regionId;
private int categoryId;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "animal")
private List<Attributes> attributes;
}
public class Attributes {
private long id;
@ManyToOne(fetch = FetchType.LAZY)
private Animal animal;
private String name;
private String value;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Detail detail;
}
public class Detail {
private long id;
private String size;
private String type;
}
This is part of a Spring Boot application.
What I would like to achieve is to query Animal by both their own attributes and by attributes in Details.
My query needs to look like this:
GET: /animal/{regionId}/{categoryId}?size=medium,large&type=carnivorous,herbivore
This would mean that I need to request all animals that have a certain regionId and categoryId and that also have Details with size and type within the value list provided. Also - and I think this is the tricky part - the size and type parameters are optional, so the query needs to take that into account.
Currently I have a PlanReposiory that extends CrudRepository and provides basic query methods for the Plan entity.
I was trying to wrap my head around the Criteria API to figure out a way to use it to achieve this goal, but I don't understand how I can put all that in my repository. Any ideas?
Upvotes: 0
Views: 2487
Reputation: 36223
You should have a look at Spring Data JPA Specifications:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications
You have to extend your Repository from JpaSpecificationExecutor
public interface CustomerRepository
extends CrudRepository<Customer, Long>, JpaSpecificationExecutor {
…
}
And then you the a findAll method that takes Specification paramter:
List<T> findAll(Specification<T> spec);
Then you can create your specification based on the parameters passed in the URL:
public static Specification<Animal> bySizeAndType(String size, String type) {
return new Specification<Animal>() {
public Predicate toPredicate(Root<Animal> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
// JOIN Attributes
// JOIN Detail
if (size != null) {
// add condition
}
if (type != null) {
// add condition
}
return builder.where(...);
}
};
}
I hope this helps.
Upvotes: 3