源码

SimpleJpaRepository的定义如下:

  1. /**
  2. * Default implementation of the {@link org.springframework.data.repository.CrudRepository} interface. This will offer
  3. * you a more sophisticated interface than the plain {@link EntityManager} .
  4. *
  5. * @author Oliver Gierke
  6. * @author Eberhard Wolff
  7. * @author Thomas Darimont
  8. * @author Mark Paluch
  9. * @author Christoph Strobl
  10. * @author Stefan Fussenegger
  11. * @author Jens Schauder
  12. * @author David Madden
  13. * @author Moritz Becker
  14. * @param <T> the type of the entity to handle
  15. * @param <ID> the type of the entity's identifier
  16. */
  17. @Repository
  18. @Transactional(readOnly = true)
  19. public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {

解读:

SimpleJpaRepository实现了JpaRepositoryImplementation接口。

JpaRepositoryImplementation的定义如下:

  1. /**
  2. * SPI interface to be implemented by {@link JpaRepository} implementations.
  3. *
  4. * @author Oliver Gierke
  5. * @author Stefan Fussenegger
  6. * @author Jens Schauder
  7. */
  8. @NoRepositoryBean
  9. public interface JpaRepositoryImplementation<T, ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
  10.  
  11. /**
  12. * Configures the {@link CrudMethodMetadata} to be used with the repository.
  13. *
  14. * @param crudMethodMetadata must not be {@literal null}.
  15. */
  16. void setRepositoryMethodMetadata(CrudMethodMetadata crudMethodMetadata);
  17.  
  18. /**
  19. * Configures the {@link EscapeCharacter} to be used with the repository.
  20. *
  21. * @param escapeCharacter Must not be {@literal null}.
  22. */
  23. default void setEscapeCharacter(EscapeCharacter escapeCharacter) {
  24.  
  25. }
  26. }

解读:

JpaRepositoryImplementation接口继承了JpaSpecificationExecutor。

类图

调用链路

观察SimpleJpaRepository中findOne(Example<S> example)方法的实现,代码如下:

  1. /*
  2. * (non-Javadoc)
  3. * @see org.springframework.data.repository.query.QueryByExampleExecutor#findOne(org.springframework.data.domain.Example)
  4. */
  5. @Override
  6. public <S extends T> Optional<S> findOne(Example<S> example) {
  7.  
  8. try {
  9. return Optional
  10. .of(getQuery(new ExampleSpecification<S>(example, escapeCharacter), example.getProbeType(), Sort.unsorted())
  11. .getSingleResult());
  12. } catch (NoResultException e) {
  13. return Optional.empty();
  14. }
  15. }

解读:

此方法由QueryByExampleExecutor接口定义。

观察SimpleJpaRepository中findOne(@Nullable Specification<T> spec)方法的实现,代码如下:

  1. /*
  2. * (non-Javadoc)
  3. * @see org.springframework.data.jpa.repository.JpaSpecificationExecutor#findOne(org.springframework.data.jpa.domain.Specification)
  4. */
  5. @Override
  6. public Optional<T> findOne(@Nullable Specification<T> spec) {
  7.  
  8. try {
  9. return Optional.of(getQuery(spec, Sort.unsorted()).getSingleResult());
  10. } catch (NoResultException e) {
  11. return Optional.empty();
  12. }
  13. }

解读:

此方法由JpaSpecificationExecutor接口定义。

小结:

上述两个findOne方法最终都是调用了如下getQuery方法:

  1. /**
  2. * Creates a {@link TypedQuery} for the given {@link Specification} and {@link Sort}.
  3. *
  4. * @param spec can be {@literal null}.
  5. * @param domainClass must not be {@literal null}.
  6. * @param sort must not be {@literal null}.
  7. * @return
  8. */
  9. protected <S extends T> TypedQuery<S> getQuery(@Nullable Specification<S> spec, Class<S> domainClass, Sort sort) {
  10.  
  11. CriteriaBuilder builder = em.getCriteriaBuilder();
  12. CriteriaQuery<S> query = builder.createQuery(domainClass);
  13.  
  14. Root<S> root = applySpecificationToCriteria(spec, domainClass, query);
  15. query.select(root);
  16.  
  17. if (sort.isSorted()) {
  18. query.orderBy(toOrders(sort, root, builder));
  19. }
  20.  
  21. return applyRepositoryMethodMetadata(em.createQuery(query));
  22. }

解读:

getQuery方法调用了applySpecificationToCriteria方法,该方法的实现如下:

  1. /**
  2. * Applies the given {@link Specification} to the given {@link CriteriaQuery}.
  3. *
  4. * @param spec can be {@literal null}.
  5. * @param domainClass must not be {@literal null}.
  6. * @param query must not be {@literal null}.
  7. * @return
  8. */
  9. private <S, U extends T> Root<U> applySpecificationToCriteria(@Nullable Specification<U> spec, Class<U> domainClass,
  10. CriteriaQuery<S> query) {
  11.  
  12. Assert.notNull(domainClass, "Domain class must not be null!");
  13. Assert.notNull(query, "CriteriaQuery must not be null!");
  14.  
  15. Root<U> root = query.from(domainClass);
  16.  
  17. if (spec == null) {
  18. return root;
  19. }
  20.  
  21. CriteriaBuilder builder = em.getCriteriaBuilder();
  22. Predicate predicate = spec.toPredicate(root, query, builder);
  23.  
  24. if (predicate != null) {
  25. query.where(predicate);
  26. }
  27.  
  28. return root;
  29. }

解读:

applySpecificationToCriteria方法调用了Specification的toPredicate方法,该方法是一个抽象方法,其定义如下:

  1. /**
  2. * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
  3. * {@link Root} and {@link CriteriaQuery}.
  4. *
  5. * @param root must not be {@literal null}.
  6. * @param query must not be {@literal null}.
  7. * @param criteriaBuilder must not be {@literal null}.
  8. * @return a {@link Predicate}, may be {@literal null}.
  9. */
  10. @Nullable
  11. Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);

解读:

纵观前述调用过程可知,此处Specification的toPredicate方法由findOne方法传递给getQuery方法的参数对应的类实现。

从findOne(Example<S> example)的实现可知,toPredicate方法由参数new ExampleSpecification<S>(example, escapeCharacter)对应ExampleSpecification类实现。

ExampleSpecification

由前面的类图可知,ExampleSpecification是SimpleJpaRepository的内部类,其定义如下:

  1. /**
  2. * {@link Specification} that gives access to the {@link Predicate} instance representing the values contained in the
  3. * {@link Example}.
  4. *
  5. * @author Christoph Strobl
  6. * @since 1.10
  7. * @param <T>
  8. */
  9. private static class ExampleSpecification<T> implements Specification<T> {
  10.  
  11. private static final long serialVersionUID = 1L;
  12.  
  13. private final Example<T> example;
  14. private final EscapeCharacter escapeCharacter;
  15.  
  16. /**
  17. * Creates new {@link ExampleSpecification}.
  18. *
  19. * @param example
  20. * @param escapeCharacter
  21. */
  22. ExampleSpecification(Example<T> example, EscapeCharacter escapeCharacter) {
  23.  
  24. Assert.notNull(example, "Example must not be null!");
  25. Assert.notNull(escapeCharacter, "EscapeCharacter must not be null!");
  26.  
  27. this.example = example;
  28. this.escapeCharacter = escapeCharacter;
  29. }
  30.  
  31. /*
  32. * (non-Javadoc)
  33. * @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.persistence.criteria.Root, javax.persistence.criteria.CriteriaQuery, javax.persistence.criteria.CriteriaBuilder)
  34. */
  35. @Override
  36. public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  37. return QueryByExamplePredicateBuilder.getPredicate(root, cb, example, escapeCharacter);
  38. }
  39. }

解读:

ExampleSpecification实现了Specification接口中的toPredicate方法。

小结:

如果需要调用SimpleJpaRepository的findOne方法,需要构造Specification或者Example对应的实例。

示例:

以匿名内部类的形式构造Specification对应的实例

  1. Specification<User> specification = new Specification<>() {
  2. @Override
  3. public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  4. Path<Integer> path = root.get("id");
  5. return cb.lt(path, id);
  6. }
  7. };

Note:

有如下一些方法调用了getQuery方法

Spring Data JPA:解析SimpleJpaRepository的更多相关文章

  1. spring data jpa 全面解析(实践 + 源码分析)

    前言 本文将从示例.原理.应用3个方面介绍spring data jpa. 以下分析基于spring boot 2.0 + spring 5.0.4版本源码 概述 JPA是什么? JPA (Java ...

  2. 【spring boot 系列】spring data jpa 全面解析(实践 + 源码分析)

    前言 本文将从示例.原理.应用3个方面介绍spring data jpa. 以下分析基于spring boot 2.0 + spring 5.0.4版本源码 概述 JPA是什么? JPA (Java ...

  3. Spring Data Jpa系列教程--------实体解析和关联关系

    Spring Data Jpa是基于HIbernate开发的,所以建立实体建的实体和映射关系需要好好好的去了解一下,本文有以下内容,实体管理器介绍,实体与数据库表的映射介绍,关联关系(一对多,多对多) ...

  4. Spring Data JPA:解析CriteriaBuilder

    源码 在Spring Data JPA相关的文章[地址]中提到了有哪几种方式可以构建Specification的实例,该处需要借助CriteriaBuilder,回顾一下Specification中t ...

  5. 快速搭建springmvc+spring data jpa工程

    一.前言 这里简单讲述一下如何快速使用springmvc和spring data jpa搭建后台开发工程,并提供了一个简单的demo作为参考. 二.创建maven工程 http://www.cnblo ...

  6. Spring Data JPA 入门Demo

    什么是JPA呢? 其实JPA可以说是一种规范,是java5.0之后提出来的用于持久化的一套规范:它不是任何一种ORM框架,在我看来,是现有ORM框架在这个规范下去实现持久层. 它的出现是为了简化现有的 ...

  7. Spring Data JPA入门

    1. Spring Data JPA是什么 它是Spring基于ORM框架.JPA规范封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作.它提供了包括增删改查等在内的常用功能, ...

  8. Spring Data JPA(官方文档翻译)

    关于本书 介绍 关于这本指南 第一章 前言 第二章 新增及注意点 第三章 项目依赖 第四章 使用Spring Data Repositories 4.1 核心概念 4.2 查询方法 4.3 定义rep ...

  9. spring data jpa(一)

    第1章     Spring Data JPA的快速入门 1.1   需求说明 Spring Data JPA完成客户的基本CRUD操作 1.2   搭建Spring Data JPA的开发环境 1. ...

  10. Spring Data JPA入门及深入

    一:Spring Data JPA简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问 ...

随机推荐

  1. C#版Nebula客户端编译

    一.需求背景 从Nebula的Github上可以发现,Nebula为以下语言提供了客户端SDK: nebula-cpp nebula-java nebula-go nebula-python nebu ...

  2. C语言:随机抽奖

    #include <stdio.h> #include <stdlib.h> //<stdlib.h>用于调用 rand(), #include <time. ...

  3. excel带格式复制python

    openpyxl 复制cell单元格包括所有样式 target_cell.data_type = source_cell.data_type target_cell.fill = copy(sourc ...

  4. ajax请求对返回数据data的处理

    1,ajax请求会根据响应头的返回数据类型对返回的数据data变量进行不同的处理 $.get("data/user-permission-submit-" + ddo.manipu ...

  5. python之数据驱动ddt操作(方法一)

    下载ddt并安装 Pip install ddt 或者官网下载安装 http://ddt.readthedocs.io/en/latest/ https://github.com/txels/ddt ...

  6. Python - list 列表常见方法

    list.append(x) 介绍 在列表的末尾添加一个元素 相当于  a[len(a):] = [x] 返回值 None 栗子 # append a = [1, 2, 3] b = [4, 5, 6 ...

  7. kali操作系统添加中文输入法

    今天一通操作真心累啊.想安装搜狗输入法,百度搜索了好多 三步走:https://blog.csdn.net/qq_44110340/article/details/101382732 一顿操作猛如虎, ...

  8. 第十篇 -- 下拉列表框QComboBox

    效果图: ui_ComboBox.py # -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'ui ...

  9. Volitle

    缓存一致性协议 最出名的是Intel的MESI协议,该协议保证了每个缓存中使用的共享变量的副本是一致的.其思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会 ...

  10. DC-6靶机

    仅供个人娱乐 靶机信息 下载地址:https://download.vulnhub.com/dc/DC-6.zip 一.主机发现 nmap -sn 192.168.216.0/24 二.端口扫描 nm ...