Spring JPA规范

spring-data-jpa所有的语法规定如下图:

JPA标准对象理解

官方解释:

     * Root<T> root:代表了可以查询和操作的实体对象的根,

     *              可以通过它的 Path<Y> get(String attributeName); 这个方法拿到我们要操作的字段

     *              注意:只可以拿到对应的T的字段(Employee)

     * CriteriaQuery<?> query:代表一个specific的顶层查询对象

     *              包含查询的各个部分,比如select,from,where,group by ,order by 等

     *              简单理解 就是它提供 了查询ROOT的方法(where,select,having)

     * CriteriaBuilder cb:用来构建CriteriaQuery的构建器对象(相当于条件或者说条件组合)

     *              构造好后以Predicate的形式返回

     * PageRequest代表分页信息,PageRequest里面的Sort对象是排序信息   

     */

/**

* 非官方理解:

* 查询的时候就需要给一个标准(规范)

*  -》 根据规范(这个规范我们可以先简单理解为查询的条件)进行查询

*

*      Root:查询哪个表(定位到表和字段-> 用于拿到表中的字段)

*            可以查询和操作的实体的根

*              Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似

*             Root<Employee> 相当于 from Employee

*             Root<Product> 相当于  from Product

*      CriteriaQuery:查询哪些字段,排序是什么(主要是把多个查询的条件连系起来)

*      CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么方式

*                      主要判断关系(和这个字段是相等,大于,小于like等)

*      Predicate(Expression):单独每一条查询条件的详细描述 整个 where xxx=xx and yyy=yy ...

*/

CriteriaBuilder对象

CriteriaBuilder builder = em.getCriteriaBuilder();

CriteriaQuery<Student> query = builder.createQuery(Student.class);

CriteriaQuery对象

Root<Student> root = query.from(Student.class);

接下来

Predicate p1 = builder.like(root.<String> get("name"), "%" + student.getName() + "%");

Predicate p2 = builder.equal(root.<String> get("password"), student.getPassword());

query.where(p1, p2);

大致过程创建builder => 创建Query => 构造条件 => 查询

Spring jpa data封装

/**

     * Applies the given {@link Specification} to the given {@link CriteriaQuery}.

     *

     * @param spec can be {@literal null}.

     * @param query must not be {@literal null}.

     * @return

     */

    private <S> Root<T> applySpecificationToCriteria(Specification<T> spec, CriteriaQuery<S> query) {

        Assert.notNull(query);

        Root<T> root = query.from(getDomainClass());

        if (spec == null) {

            return root;

        }

        CriteriaBuilder builder = em.getCriteriaBuilder();

        Predicate predicate = spec.toPredicate(root, query, builder);


        if (predicate != null) {

            query.where(predicate);

        }

        return root;

    }

In查询

if(!CollectionUtils.isEmpty(ids)) {

    In<Long> in = cb.in(root.<Long> get("id"));

    for (Long id : ids) {

        in.value(id);

    }

    query.where(in);

}

@Lock可以使用悲观锁

@Version使用乐观锁

 

Join查询

@Override

    public List<Employee> findByCompanyName(final String companyName) {

        

        List<Employee> employeeList = employeeRepository.findAll(new Specification<Employee>() {

            public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

//                ListJoin<Employee, Company> companyJoin = root.join(root.getModel().getList("companyList", //Company.class), JoinType.LEFT);

                //Join对象与Root对象分别指代Company,Employee对象

                Join<Employee, Company> companyJoin = root.join("companyList", JoinType.LEFT);

                return cb.equal(companyJoin.get("name"), companyName);

            }

        });

        

        return employeeList;

    }

需要多个对象进行Join

@Override

    public List<Employee> findByCompanyName(final String companyName, final String wage) {

        

        List<Employee> employeeList = employeeRepository.findAll(new Specification<Employee>() {

            public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

//                ListJoin<Employee, Company> companyJoin = root.join(root.getModel().getList("companyList", //Company.class), JoinType.LEFT);

                Join<Employee, Company> companyJoin = root.join("companySet", JoinType.LEFT);

                Join<Employee, Wage> wageJoin = root.join("wageSet", JoinType.LEFT);

                Predicate p1 = cb.equal(companyJoin.get("name"), companyName);

                Predicate p2 = cb.equal(wageJoin.get("name"), wage);

//              return cb.and(p1, p2);根据spring-data-jpa的源码,可以返回一个Predicate,框架内部会自动做query.where(p)的操作,也可以直接在这里处理,然后返回null,///              也就是下面一段源码中的实现

                query.where(p1, p2);

                return null;

            }

        });

        

        return employeeList;

    }

虽然说JPA中这种方式查询会存在着多次级联查询的问题,对性能有所影响,但是在一般的企业级应用当中,为了开发的便捷,这种性能牺牲一般来说是可以接受的。

  特别的:在一对多中或者多对一中,即便是fetch为eager,也会先查询主对象,再查询关联对象,但是在eager的情况下虽然是有多次查询问题,但是没有n+1问题,关联对象不会像n+1那样多查询n次,而仅仅是把关联对象一次性查询出来,因此,在企业级应用当中,访问量不大的情况下一般来说没什么问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值