zl程序教程

您现在的位置是:首页 >  其他

当前栏目

JPA入门

入门 jpa
2023-09-14 09:14:52 时间

JPA概述

在这里插入图片描述
1、简介:
Java Persistence API:用于对象持久化的 API。
Java EE 5.0 平台标准的 ORM规范,使得应用程序以统一的方式访问持久层。
在这里插入图片描述
2、JPA 是 hibernate 的一个抽象(就像JDBC和JDBC驱动的关系):
JPA 是规范:JPA 本质上就是一种 ORM 规范,不是ORM 框架—— 因为 JPA 并未提供 ORM 实现,它只是制订了一些规范,提供了一些编程的 API 接口,但具体实现则由 ORM 厂商提供实现。
Hibernate是实现:Hibernate 除了作为 ORM 框架之外,它也是一种 JPA 实现
从功能上来说, JPA 是 Hibernate 功能的一个子集。

3、JPA 的特点:
标准化: 提供相同的 API,这保证了基于JPA 开发的企业应用能够经过少量的修改就能够在不同的 JPA 框架下运行。

简单易用,集成方便: JPA 的主要目标之一就是提供更加简单的编程模型,在 JPA 框架下创建实体和创建 Java 类一样简单,只需要使用 javax.persistence.Entity 进行注释;JPA 的框架和接口也都非常简单。

可媲美JDBC的查询能力: JPA的查询语言是面向对象的,JPA定义了独特的JPQL,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

支持面向对象的高级特性: JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,最大限度的使用面向对象的模型。

4、JPA 技术:
ORM 映射元数据:JPA 支持 XML 和 JDK 5.0 注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。

JPA 的 API:用来操作实体对象,执行CRUD操作,框架在后台完成所有的事情,开发者从繁琐的 JDBC和 SQL代码中解脱出来。

查询语言(JPQL):这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序和具体的 SQL 紧密耦合。

JPA

  • 基于ORM思想实现的框架都称为JPA框架
  • JPA 是一个基于O/R映射的标准规范,只定义标准规则(如注解、接口),不提供实现。
  • JPA 的主要实现有Hibernate、EclipseLink 和OpenJPA 等

Spring Data JPA

对于JPA规范的再次封装,底层实现使用了Hibernate的技术,属于Spring生态的一部分。

img

JPA注解

基础注解

Entity

  • 用于定义这个对象是实体类,将成为JPA的管理对象,必用!
  • 只能用在class上,默认值是类名

Table

  • 指定数据库的表名,表示此实体对应哪张数据表
  • 可以不填,默认表名就是实体名

Id

  • 数据库主键,必须有主键
  • 可以配合@GeneratedValue定义主键生成策略

Enumerated

  • 为实体中的字段提供枚举值
  • @Enumerated默认是枚举值所在的下标(不建议用
  • @Enumerated(*.class)表示枚举本身的名称

img

  • @Enumerated(EnumType.ORDINAL)在数据库中存的是0,1
  • @Enumerated(EnumType.STRING)在数据库中存的是MIAL/FEMAIL

Transient

  • 表示该属性不是一个持久化的属性,不需要映射到数据库中
  • 有此注解,JPA持久化的时候会忽略

Column

  • 表示该属性对应到数据库中的列名
  • 不写的时候直接就是默认字段名
  • 默认允许为空
  • insertable和updatable可以选择是否在insert或者update是包含此字段
    -insertable和updatable一般多用于只读的属性,例如主键和外键等,这些字段的值通常是自动生成的

Temporal

  • 表示Date类型的属性映射到对应精度的字段
  • @Temporal(TemporalType.Date):只有日期
  • @Temporal(TemporalType.Time):只有时间
  • @Temporal(TemporalType.TimeStamp):日期+时间

联合主键注解

IdClass

  • 新建一个主键类,类中包含主键字段,此类必须实现Serializable接口,无参构造函数必须是默认的,且必须覆盖equals和hashCode方法。equals方法用于判断两个对象是否相同, EntityManger通过find方法来查找Entity时是根据equals的返回值来判断的。 在本例中, 只有对象的值完全相同或同一个对象时才返回true, 否则返回false。 hashCode方法返回当前对象的哈希码, 生成的hashCode相同的概率越小越好, 算法可以进行优化。
  • 实体中使用@IdClass(*.class)表示使用此主键类
  • 实体中对应的主键字段加上@Id

主键类:主键字段为:title和createUserId联合主键

img

实体类:

img

Embeddable和EmbeddedId注解

img

实体之间关联关系注解

OneToOne

  • 表示对象直接一对一的关系,比如一个客户记录表对应一个客户资金表
  • 注解放在字段属性上或者放在getter/setter方法上
  • 可以配置单向关联和双向关联
  • 如果是配置单向关联,则此注解只用在拥有外键的一方

img

  • OrphanRemoval:表示是否删除孤立元素,例如映射关系是一对一,或一对多。加上这个注解,即使不设置级联关系,删除一的时候,多的一方肯定是孤立元素了。
  • 尽量不适用一对一中的双向关联
  • 级联操作应该保持默认
  • 关联的地方尽量使用LAZY

ManyToOne和OneToMany

  • ManyToOne表示多对一,用在维护外键关系的一方,我们理解的多的一方
  • OneToMoney表示一对多,
  • 两个成对使用且维护关系的一方是拥有外键的一方,另一方必须配置apperBy

img

img

Repository

Spring Data里面做数据库操作的最底层的抽象接口、 最顶级的父类。

JPA查询方式

DQM(定义查询方法)

  • 一种是直接通过方法名实现
  • 另一种通过@Query手动在方法上定义

使用实例

img

DMQ方法名中支持的关键字

在这里插入图片描述
在这里插入图片描述

支持分页和排序

img

限制查询结果

img

@Query方式查询

img

like

img

原生SQL

img

参数

img

QueryByExampleExecutor

示例

img

  • 查询所有名称是“linan”结尾且公司名称是“海”开始的记录
  • 实体对象:在持久化框架中与Table对应的域对象,一个对象代表数据库表中的一条记录,如上例中person对象。在构建查询条件时,一个实体对象代表的是查询条件中的“数值”部分。如:要查询姓“linan”的客户,实体对象只能存储条件值“linan”。
  • 匹配器:ExampleMatcher对象,它是匹配“实体对象”的,表示了如何使用“实体对象”中的“值”进行查询,它代表的是“查询方式”,解释了如何去查的问题。
  • 实例:即Example对象,代表的是完整的查询条件。由实体对象(查询条件值)和匹配器(查询方式)共同创建。

就是通过一个例子来查询。要查询的是Person对象,查询条件也是一个Person对象,通过一个现有的对象作为例子,查询和这个例子相匹配的对象。

JpaSpecificationExecutor

接口

img

Specification接口

img

  1. Root: 代表了可以查询和操作的实体对象,如果将实体对象比喻成表名,那root里面就是这张表里面的字段,是JPQL的实体字段,通过.get(String var0)来获得操作的字段
  2. CriteriaQuery<?>: 代表一个specific的顶层查询对象,它包含着查询的各个部分,如: select、form、where、group by、order by 等,它提供了查询var1的的方法,常用的有 where、select、having
  3. CriteriaBuilder: 用来构建CriteriaQuery的构建器对象,其实就相当于条件或条件组合

使用Specification的要点就是CriteriaBuilder,通过这个对象来创建条件,之后返回一个Predicate对象。这个对象中就有了相应的查询需求,我们同样可以定义多个Specification,之后通过Specifications对象将其连接起来

示例

img

open-in-view

  1. 两个属性值:true或者false
  2. True: 假如我们在Controller调用了两个Service层的事务方法,那么在Controller开始执行的时候创建session,直到两个事务都结束且Controller方法执行完毕才关闭Session。
  3. False:假如我们在Controller调用了两个Service层的事务方法, 每个事务开始的时候都会创建Session,在每个事务结束之后关闭Session。。可能会引起Lazy异常。