mysql

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

2020-08-01  本文已影响0人  沉寂之舟
image.png

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


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

第1章 整体认识JPA

  1. Spring Data的子项目:

可谓范围全面,其目标就是提供一个一致的,基于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<T, ID> {
}

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的类层次关系
  1. Repository的实现类SimpleJpaRepository
public interface JpaRepositoryImplementation<T, ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
...
}

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

补充: 复习一下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<Person> findByAddressZipCode(String zipCode);

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

  1. 查询结果的处理
  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存储过程

  1. @NamedQueries预定义查询 -- 不推荐

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

  1. javax.persistence
  2. 注解列表.
  3. 关系注解
  1. LeftJoin,InnerJoin与@EntityGraph

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

  1. 关系查询的坑
上一篇下一篇

猜你喜欢

热点阅读