Spring Data JPA从入门到精通(第一部分)

image.png

传送门:
Spring Data JPA从入门到精通(第一部分)
Spring Data JPA从入门到精通(第二部分)
Spring Data JPA从入门到精通(第三部分)


所有代码均源自spring-data#2.2.6版本

第1章 整体认识JPA

  1. Spring Data的子项目:
  • spring data common
  • spring data gemfire
  • spring data jpa
  • spring data keyvalue
  • spring data LDAP
  • spring data MongoDB
  • spring data Rest
  • spring data Redis
  • spring data for apache cassandra
  • spring data for apache solr

可谓范围全面,其目标就是提供一个一致的,基于Spring的数据访问编程模型,同时仍能保留底层数据存储的特殊特性.包括了关系型DB,外部缓存Redis,流数据库cassandra,搜索引擎solr.本书重点还是关系型-JPA.

  1. Srping Data JPA 主要类结构图(图1-5) -- 目前已不是这样
    image.png

第2章 JPA基础查询方法

  1. Spring Data Common 的Repository
@Indexed
public interface Repository {
}

SpringFramework5.0引入了一个注解@Indexed,在项目中使用了@Indexed之后,编译打包的时候会在项目中自动生成META-INT/spring.components文件,这样系统会自动给实体bean增加排序功能.

参考:
https://docs.spring.io/spring/docs/5.1.12.RELEASE/spring-framework-reference/core.html#beans-scanning-index

  1. Repository的类层次关系
  • CrudRepository 接口
  • PageAndSortingRepository 接口
  • JpaRepository 接口
  1. Repository的实现类SimpleJpaRepository
  • JpaRepositoryImplementation
public interface JpaRepositoryImplementation extends JpaRepository, JpaSpecificationExecutor {
...
}

从定义可以看出,不但扩展了JpaRepository,而且还扩展了JpaSpecificationExecutor,里面都是查询的方法,而参数都是Specification类型.

补充: 复习一下JDK的动态代理实现原理

JDK-Proxy动态代理深度探究

JDK的动态代理深入解析

第3章 定义查询方法

  1. 定义查询方法的配置方法

JPARepository实现原理是采用动态代理,因此只需要扩展Spring数据接口即可,或者用@RepositoryDefinition,书里却没有说用法.

  1. 方法查询策略设置

QueryLookupStray.Key

public static enum Key {

        CREATE, USE_DECLARED_QUERY, CREATE_IF_NOT_FOUND;
}

默认为CREATE_IF_NOT_FOUND,等于前面2个结合.先查找是否有注解声明的SQL,如果没有,就根据方法名Create出来.

  1. 查询方法的创建

主要看PartTree源码,他根据前缀和属性名对方法进行切分,这个过程是可以嵌套的;例如

List findByAddressZipCode(String zipCode);

首先查找addressZipCode属性,发现没有,就根据驼峰命名找addressZip属性,还是没有,再找address属性,发现有了.然后后面的ZipCode继续找,发现正好有个同名.就part()出查询条件了.
(前提是Person有个Address属性,其中有个zipCode的String属性.)

  1. 查询结果的处理
  • 查询结果的分页和排序
    使用Pageable,Slice,Sort.
  • 限制查询结果
    使用first,top
  1. 其他形式(Stream,Future) -- 略

  2. Projections对查询结果的扩展

使用Projection可以对查询结果进行映射,用接口的方式,最简单是定义接口中属性为Entity的一个子集,这样自动就能映射到结果.同时也可以用@Value和SPEL表达式生成新的属性.甚至可以在Repository中使用泛型,由后续调用指定具体返回类型.

  1. 实现机制

QueryExecutorMethodInterceptor,居然只给了类图,这个从后面源码阅读来看,总结了JPA使用Spring FactroyBean怎么把接口编程代理对象的过程,是相当重要的.

图3-3


image.png

第4章 注解式查询方法

  1. @Query
public @interface Query {

    // 指定的SQL查询语句
    String value() default "";

    // 指定的count语句,一般用default即可
    String countQuery() default "";

    // 指定那些字段来count,一般用default即可
    String countProjection() default "";

    // 是否为原生(直接放DB运行)的SQL,默认为JQL模式,非原生.
    boolean nativeQuery() default false;

    // 名字,默认的生成规则为
    //  {@code $ domainClass}.${queryMethodName}} will be used.
    String name() default "";

    // 同上,指定一个Count的查询名称,默认为name加上".count"
    String countName() default "";
}

Query注解是直接写SQL语句查询的方式了,需要注意的是,如果使用Native=true(数据库绑定)的查询语句,Sort参数需要手工写入到语句中,而且对于分页支持不友好,尽量还是少用吧.

  1. @Param

Param给参数命名,这样再@Query中就可以不用"?1"这种顺序参数,而是使用参数名了,是的语句更为容易阅读.

  1. SpEl表达式的支持

可以直接用#{#entityname}的形式声明查询条件(${}为Properties表达式,而#entityname为保留字,JPA根据@Entity注解,读取里面的名称),这样from时候就知道表名了.

  1. @Modifying

这个用在Upate,Delete,Insert语句,声明语句执行后,参数数据发生了变化.

  1. @QueryHints

  2. @Procedure存储过程

  • 先在实体Entity上使用@NamedStoredProcedureQueries注解声明存储过程的调用方式,其中参数需要用@StoredProcedureParamter声明,并且特别指定IN,OUT
  • 然后在Repository上使用@Procdure注解调用该存储过程,也就是说存储过程内部用了什么表并不需要关心,只需要关心我们传入Repository的实体上有这个存储过程的声明.
  • 注意@Param需要与IN匹配,返回类型必须与存储过程返回值类型匹配.
  • 使用@Produce只能针对一个OUT的情况,如果存储过程有多个OUT,那就只能调用entityManager.createNamedStoredProcedureQuery,然后在调用store.getOutputParameterValue逐个获得返回值了.(这种情况,还是改改存储过程自身吧)
  1. @NamedQueries预定义查询 -- 不推荐

第5章 @Entity实例里面常用注解

  1. javax.persistence
  2. 注解列表.
  3. 关系注解
  • @JoinColumn与@OneToOne,@OneToMany,@ManyToOne
  • @OrderBy,用在@OneToMany多的那一方排序方法
  • @@JoinTabe与@ManyToMany
  1. LeftJoin,InnerJoin与@EntityGraph

关联查询自动生成的语句经常需要多次查询,如先查询1的那张表,再生成查询n的那张表,通过@EntityGraph就能关联起来一次全部查询出来.

  1. 关系查询的坑
  • 所有注解配置在字段或者全部配置在get方法,不能混用(这与@Autowired不同)
  • 双向注解在Json序列化会产生死循环,需要手工转换,或者配合@JsonIgnore使用
  • 表本身并不要求建立外键索引,使用@MappedBy需要注意
  • 级联删除是危险操作,需要仔细评估
  • @JoinColumn中name,referenceColumnName含义不易理解,可配合打印出的SQL调整
  • 关联关系建议绑定到外键上,不用非外键的表间关联.

你可能感兴趣的:(Spring Data JPA从入门到精通(第一部分))