How to write query(include subquery and exists) using JPA Criteria Builder

后端 未结 2 787
梦如初夏
梦如初夏 2021-02-06 10:39

Struggling to write the following query using JPA.

Oracle Query:

Select * from table1 s
where exists (Select 1 from table2 p
              INNER JOIN tab         


        
相关标签:
2条回答
  • 2021-02-06 11:18

    You can do it much simpler using JPA Queries or HQL instead of Criteria builders:

    SELECT e1 from Entity1 as e1 
    where exists
    (select e2 from Entity2 as e2 join e2.e3 as ent3
    where ent3.id=e1.id and e2.name='Test')
    
    0 讨论(0)
  • 2021-02-06 11:22

    I will answer the example of the simple car advertisement domain (advert, brand, model) using JpaRepository, JpaSpecificationExecutor, CriteriaQuery, CriteriaBuilder:

    • brand [one-to-many] model
    • model [one-to-many] advert

    Entities:

    @Entity
    public class Brand {
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;
      private String name;
      @OneToMany(mappedBy = "brand", fetch = FetchType.EAGER)
      private List<Model> models;
    }
    
    @Entity
    public class Model {
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;
      private String name;
      @ManyToOne
      @JoinColumn(name = "brand_id")
      private Brand brand;
    }
    
    @Entity
    public class Advert {
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;
      @ManyToOne
      @JoinColumn(name = "model_id")
      private Model model;
      private int year;
      private int price;
    }
    

    Repository:

    public interface AdvertRepository
      extends JpaRepository<Advert, Long>, JpaSpecificationExecutor<Advert> {
    }
    

    Specification:

    public class AdvertSpecification implements Specification<Advert> {
      private Long brandId;
    
      public AdvertSpecification(Long brandId) {
        this.brandId = brandId;
      }
    
      @Override
      public Predicate toPredicate(Root<Advert> root,
                                   CriteriaQuery<?> query,
                                   CriteriaBuilder builder) {
    
        Subquery<Model> subQuery = query.subquery(Model.class);
        Root<Model> subRoot = subQuery.from(Model.class);
    
        Predicate modelPredicate = builder.equal(root.get("model"), subRoot.get("id"));
    
        Brand brand = new Brand();
        brand.setId(brandId);
        Predicate brandPredicate = builder.equal(subRoot.get("brand"), brand);
    
        subQuery.select(subRoot).where(modelPredicate, brandPredicate);
        return builder.exists(subQuery);
      }
    }
    

    Effect is this Hibernate SQL:

    select advert0_.id as id1_0_,
           advert0_.model_id as model_id5_0_,
           advert0_.price as price3_0_,
           advert0_.year as year4_0_
    from advert advert0_
    where exists (select model1_.id from model model1_
                  where advert0_.model_id=model1_.id
                  and model1_.brand_id=?)
    
    0 讨论(0)
提交回复
热议问题