简体   繁体   中英

Criteria API in Spring Boot

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM