初步认识JPA(Java Persistence API)和Hibernate
- JPA (Java Persistence API)
JPA是一个Java规范(接口规范),由Java EE(现为Jakarta EE)定义,用于简化在Java应用程序中与数据库进行交互的操作。JPA主要用于对象关系映射(ORM),它允许Java对象与数据库表进行映射,简化了持久化操作。
规范而非实现:JPA本身并不提供实现,它定义了一组标准接口和规则,供开发人员使用,具体的实现由第三方库提供。
标准接口:JPA提供了一些重要的接口,如 EntityManager、EntityManagerFactory,以及用于查询的JPQL(Java Persistence Query Language)。
JPA提供的功能:包括实体映射、查询、事务管理等,旨在简化数据库操作。
JPA的目标是使Java开发者能够以面向对象的方式处理数据库操作,避免使用大量SQL代码。
- Hibernate
Hibernate是一个开源的Java ORM框架,它实现了JPA规范。简而言之,Hibernate是JPA的一个实现,但Hibernate在JPA之外还有自己的一些额外特性和功能。
JPA的实现:Hibernate完全实现了JPA规范,并且提供了一个称为Hibernate ORM的框架。作为JPA的实现,Hibernate让开发者能够通过JPA接口来进行数据库交互。
额外功能:Hibernate提供了JPA之外的许多特性,例如HQL(Hibernate Query Language)、二级缓存、更高效的批量操作、自动生成数据库表等,这些功能不完全属于JPA规范的一部分。
独立功能:如果你不想依赖JPA,可以直接使用Hibernate提供的API进行数据库操作。
- JPA与Hibernate的关系
JPA是规范,Hibernate是实现。JPA定义了持久化管理的标准,而Hibernate提供了这些标准的实现。你可以使用Hibernate来执行JPA的操作。
JPA的实现不止Hibernate。除了Hibernate之外,其他一些框架也实现了JPA规范,例如EclipseLink、OpenJPA等。因此,Hibernate只是JPA的一个常见实现。
JPA提供标准化的接口和方法,使得不同的ORM框架(包括Hibernate)可以相互替代,保证代码的移植性。如果你选择使用JPA,可以在不同的框架之间切换而不需要大量修改代码。
常用注解
用于标记实体类的注解
@Entity
该注解用于标记一个类是一个实体类,Hibernate 会将其映射到数据库中的一张表。
@Table
指定实体类所对应的数据库表名。name 属性用于指定表的名称,schema 用于指定数据库的模式。
@Id
该注解用于标记实体类的主键字段。
@Column
用于映射数据库表中的列,支持设置列的名称、长度、是否可为空等。
@GeneratedValue
用于定义主键生成策略,常见的生成策略有:
GenerationType.IDENTITY: 使用数据库的自动增长字段。
GenerationType.SEQUENCE: 使用数据库的序列生成主键(常用于 Oracle)。
GenerationType.AUTO: Hibernate 会自动选择合适的主键生成策略。
用于映射实体类之间关系和级联删除的注解:
@OneToMany: 一对多关系
@ManyToOne: 多对一关系
@ManyToMany: 多对多关系
@OneToOne: 一对一关系
关于实体类关系映射级联操作注解的使用
- CascadeType.PERSIST
描述:当对父实体执行持久化操作(如EntityManager.persist())时,也会自动执行相应子实体的持久化操作。
应用场景:当你想要在保存父实体时,自动保存与其关联的子实体(例如,父实体和子实体通过@OneToMany或@ManyToOne关系关联)。 - CascadeType.MERGE
描述:当对父实体执行合并操作(如EntityManager.merge())时,也会自动执行相应子实体的合并操作。
应用场景:适用于你想要在更新父实体时,自动更新与其关联的子实体。 - CascadeType.REMOVE
描述:当对父实体执行删除操作(如EntityManager.remove())时,也会自动删除与其关联的子实体。
应用场景:适用于当父实体删除时,自动删除所有相关的子实体。常见于父子实体之间的“一对多”或“多对一”关系。 - CascadeType.REFRESH
描述:当对父实体执行刷新操作(如EntityManager.refresh())时,也会自动刷新与其关联的子实体。
应用场景:适用于当你想要刷新父实体时,也刷新子实体的情况。通常用于同步父子实体的最新状态。
示例:@ManyToMany中应用
当配置了CascadeType.REFRESH,新增或修改user时会自动刷新与role之间的关联关系(sys_user_role表),但是并不会对role实体本身做任何改动。
@Entity
@Table(name = "sys_user")
@Data
public class SysUser
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Integer userId;
@Column(name = "user_code")
private String userCode;
@ManyToMany(cascade = {CascadeType.REFRESH}, fetch = FetchType.LAZY)
@JoinTable(name = "sys_user_role",
joinColumns = {@JoinColumn(name = "user_id")},
inverseJoinColumns = {@JoinColumn(name = "role_id")})
private Set<SysRole> roles;
}
- CascadeType.DETACH
描述:当对父实体执行分离操作(如EntityManager.detach())时,也会自动分离与其关联的子实体。
应用场景:适用于当父实体从持久化上下文中分离时,子实体也应该从持久化上下文中分离。一般用于从持久化上下文中完全移除父子实体。 - CascadeType.ALL
描述:包括了以上所有的级联操作(PERSIST, MERGE, REMOVE, REFRESH, DETACH)。这意味着对父实体的操作会自动传播到子实体上。
应用场景:适用于父子实体之间需要所有级联操作的场景。例如,父实体的增、删、改、查操作都应当同时作用到子实体上。