Spring Data JPA简单使用

413 阅读4分钟

Spring Data JPA

jpa操作的操作步骤

image-20211107195640937.png

基础配置

  • 在配置自动创建数据库表时:

    • create 程序运行时创建数据库表(如果有表则删除在创建,没有则创建)
    • update 程序运行时出创建表(有表不会在创建)
    • none 不创建

image-20211112142331525.png

常用注解说明

  • @Entity(声明实体类)

  • @Table(配置实体类和表的映射关系)

  • @Id(声明主键)

  • @GeneratedValue(配置主键的生成策略)

    • strategy(属性)=GenerationType.IDENTITY 自增 注:数据库支持自增
    • GenerationType.SEQUENCE 序列 注:支持序列oracle数据库使用
    • GenerationType.TABLE 注:jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
    • GenerationType.AUTO 注:由程序自动的帮助我们选择主键生成策略
  • @GenericGenerator注解----自定义主键生成策略

  • @Column(配置属性和字段的映射的关系)

查询

1、Dao层

  • 继承JpaRepository<操作的实体类类型,实体类中主键属性的类型>

    • 封装了基本的CRUD操作
  • 继承JpaSpecificationExecutor<操作的实体类类型>

    • 封装了复杂的查询(分页)
  • 基本查询

image-20211110145130379.png

2、InvocationHandler 动态代理的方式

image-20211107195740906.png

  • 调用SimpleJpaRepository里面的方法,后在对base-package包下的dao接口进行动态代理增强。

注:通过JdkDynamicAopProxy的invoke方法创建了一个动态代理对象

SimpleJpaRepository当中封装了jpa的操作,借助jpa 的api完成数据库的curd

通过hibernate完成数据库的操作,底层封装的jdbc

image-20211107195757415.png

3、复杂查询

  • Transactional事务

    • @Rollback:@Rollback(value=false/true)设置是否自动回滚

    • findOne与getOne的区别:

      • findOne:立即加载
      • getOne:延迟加载,需要加入事务注解,什么时候用什么时候查询
  • jpql查询方式(特点:语法或关键字和sql语句类似,查询的是类和类中的属性)

    • 需要将jpql语句配置到接口方法上:

      • 特有的查询:需要在dao接口上配置方法

      • 在新添加的方法上,使用注解的形式配置jpql查询语句

      • 注解:@Query (value=“ ”)

        对多个占位符参数:赋值的时候,默认情况下,占位符的位置需要和方法的参数中的位置保持一致。

        可以指定占位符的参数位置:?索引的方式,指定次占位的取值来源

  • sql语句的查询

    • 特有的查询:需要dao接口上的配置方法

    • 在新添加的方法上,使用注解的形式配置sql查询语句

    • 注解:@Query

      • value::jpql语句 | sql语句
      • nativeQuery:false(使用jpql查询)| true(使用本地查询:sql查询)是否使用本地查询
  • 方法名称规则查询

    • 是对jpql查询,更加深入的一层封装

    • 需要安装springdatajpa提供的方法名称规则定义方法,不需要在配置jpql语句,完成查询findBy开头:代表查询

      • 对象中属性的名称(首字母大写)

      • 含义:根据属性名进行查询

image-20211107195830484.png

多表查询

1、Specifications动态查询

image-20211107195931918.png

  • 动态查询完成多条件拼接

image-20211107195952665.png

  • 模糊匹配查询列表

image-20211107200016576.png

  • 排序

image-20211107200032574.png

  • 分页

image-20211107200047725.png

2、多表之间的关系和操作多表的操作步骤

表关系:
  • 一对一

  • 一对多

    • 一的一方:主表
    • 多的一方:从表
    • 外键:需要在从表上新建一列作为外键,他的取值来源于主表的主键
  • 多对多

    • 中间表:中间表中最少应该由两个字段组成,这两个字段作为外键只想两张表的主键,又组成联合主键
实体类中的关系
  • 包含关系:可以通过实体类中的包含关系描述表关系
  • 继承关系
分析步骤
  • 明确表关系
  • 确定表关系(描述、外键|中间表)
  • 编写实体类,在实体类中描述表关系(包含关系)
  • 配置映射关系

3、完成多表操作

image-20211107200105912.png

  • 在实体类中配置一对多关系

    • 例:描述关系:

    • 配置关系:使用注解形式配置

      • 声明关系:@OneToMany(配置一对多)

        @JionColumn配置外键(中间表)

@OneToMany(targetEntity = 对方对象的字节码对象)
@JionColumn(name ="外键字段名称",referencedCoulumnName ="参照的主表的主键字段名称" )
private Set<linkman> l = new HashSet<>();
  • 在一的一方放弃维护全关系
@OneToMany(mappedBy = "customer")
//mappedBy:对方配置关系的属性名称
private Set<linkman> l = new HashSet<>();
  • 配置实体类中的多对一关系

    • 配置关系:使用注解形式配置

      • 声明关系:@OneToMany(配置一对多)

        @JionColumn配置外键(中间表)

@OneToMany(targetEntity = 对方对象的字节码对象)
@JionColumn(name ="外键字段名称",referencedCoulumnName ="参照的主表的主键字段名称" )
private Customer customer;
  • 添加

在impl中操作时需要加入配置关系:一对多

 customer.getLinkman().add(linkman)

多对一

linkman.setCustomer(customer)
  • 删除

image-20211107200137685.png

  • 级联

    配置级联关系

@OneToMany(mappedBy = "customer",cascade = "CascadeType.All")
//mappedBy:对方配置关系的属性名称
//cascade:配置级联关系 
private Set<linkman> l = new HashSet<>();
多对多操作
  • 明确表关系:多对多关系

  • 确定表关系(描述、外键|中间表):中间表

  • 编写实体类,在实体类中描述表关系(包含关系)

    用户:包含角色的集合

    角色:包含用户的集合

  • 配置映射关系

    角色到用户的多对多关系

用户到角色的多对多关系

多对多的关系中,被动方放弃维护权

对象导航查询
  • 一的一方查询多的一方

默认使用的是延迟加载的形式查询,调用get方法并不会立即发送查询,而是在使用关联对象的时候才会查询

如果不想用延迟加载:修改配置,将延迟加载改为立即加载,fetch 需要配置到多表映射的注解上

例:对象导航查询,此客户下的所有联系人
    Set<Linkman> l = customer.getLinkmans();
  • 多的一方查询一的一方

    默认立即加载,fetch = FetchType.LZAY

查询机制:

超类

  • @MappedSuperclass(用在父类上面的,用来标识父类)

    • 用法:在项目开发中使用JPA的@MappedSuperclass注解将实体类的多个属性分别封装到不同的非实体类中。通过这个注解,我们可以将该实体类当成基类实体,它不会隐射到数据库表,但继承它的子类实体在隐射时会自动扫描该基类实体的隐射属性,添加到子类实体的对应数据库表中。例如,数据库表中都需要id来表示编号,id是这些映射实体类的通用的属性,交给jpa统一生成主键id编号,那么使用一个父类来封装这些通用属性,并用@MappedSuperclas标识。

    • 注意:

      • 标注为@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。
      • 标注为@MappedSupclass的类不能在标注@Entity或@Table注解,也不需要