jpa和hibernate_JPA和Hibernate的Java持久性,第1部分:实体和关系

jpa和hibernate

Java Persistence API(JPA)是一种Java规范,可在关系数据库和面向对象的编程之间架起桥梁。 这个由两部分组成的教程介绍了JPA,并说明了如何将Java对象建模为JPA实体,如何定义实体关系以及如何在Java应用程序中将JPA的EntityManager和Repository模式一起使用。

请注意,本教程使用Hibernate作为JPA提供程序。 大多数概念可以扩展到其他Java持久性框架。

什么是JPA?

请参阅“ 什么是JPA?Java Persistence API简介 ”以了解JPA和相关框架(包括EJB 3.0)的发展。 和JDBC。

JPA中的对象关系

自1970年代以来,关系数据库已经作为一种存储程序数据的手段而存在。 尽管当今的开发人员有很多关系数据库的替代方案 ,但是这种类型的数据库是可伸缩的并且易于理解,并且仍广泛用于小型和大型软件开发中。

关系数据库上下文中的Java对象定义为实体 。 实体放置在表中,在表中它们占据列和行。 程序员使用外键联接表来定义实体之间的关系-即一对一,一对多和多对多关系。 我们还可以使用SQL(结构化查询语言)使用外键约束来检索单个表和多个表中的数据并与之交互。 关系模型是扁平的,但是开发人员可以编写查询来检索数据并从该数据构造对象。

对象关系阻抗不匹配

您可能对术语“ 对象关系阻抗不匹配”很熟悉,这是将数据对象映射到关系数据库所面临的挑战。 之所以发生这种不匹配,是因为面向对象的设计不限于一对一,一对多和多对多的关系。 相反,在面向对象的设计中,我们考虑对象,它们的属性和行为以及对象之间的关系。 封装和继承是两个示例:

  • 如果一个对象包含另一个对象,我们可以通过封装 -一个has-a关系来定义。
  • 如果一个对象是另一个对象的特化,我们通过继承 -is -a关系来定义。

关联,聚合,组成,抽象,泛化,实现和依赖项都是面向对象的编程概念,可能很难映射到关系模型。

ORM:对象关系映射

面向对象的设计与关系数据库建模之间的不匹配导致了专门为对象关系映射(ORM)开发的一类工具。 Hibernate,EclipseLink和iBatis等ORM工具将关系数据库模型(包括实体及其关系)转换为面向对象的模型。 这些工具中有许多是在JPA规范之前存在的,但是没有标准,它们的功能就取决于供应商。

Java Persistence API(JPA)于2006年作为EJB 3.0的一部分首次发布,它提供了一种注释对象的标准方法,以便可以将它们映射并存储在关系数据库中。 该规范还定义了与数据库交互的通用结构。 拥有适用于Java的ORM标准可为供应商实现带来一致性,同时还具有灵活性和附加功能。 例如,虽然原始JPA规范适用于关系数据库,但某些供应商实现已扩展了JPA以用于NoSQL数据库。

JPA的演变

JPA的第一个版本1.0版于2006年通过Java社区流程(JCP)作为Java规范请求(JSR)220发布。版本2.0(JSR 317)于2009年发布,版本2.1(JSR 338)于2013年发布,并在2017年发布了2.2版(JSR 338的维护版本)。已选择JPA 2.2包含在Jakarta EE中并正在进行开发。

JPA入门

Java Persistence API是一种规范,而不是一种实现:它定义了一个通用抽象,您可以在代码中使用该抽象来与ORM产品进行交互。 本节回顾了JPA规范的一些重要部分。

您将学习如何:

  • 在数据库中定义实体,字段和主键。
  • 在数据库中的实体之间创建关系。
  • 使用EntityManager及其方法。

定义实体

为了定义实体,您必须创建一个使用@Entity注释进行注释的类。 @Entity批注是标记批注 ,用于发现持久性实体。 例如,如果您要创建一个图书实体,则可以按以下方式对其进行注释:


@Entity
public class Book {
   ...
}

默认情况下,该实体将映射到Book表(由给定的类名确定)。 如果您想将此实体映射到另一个表(以及可选的特定模式),则可以使用@Table注释来实现。 这是将Book类映射到BOOKS表的方法:


@Entity
@Table(name="BOOKS")
public class Book {
   ...
}

如果BOOKS表位于PUBLISHING模式中,则可以将该模式添加到@Table批注中:


@Table(name="BOOKS", schema="PUBLISHING")

将字段映射到列

将实体映射到表后,下一个任务是定义其字段。 字段在类中定义为成员变量,每个字段的名称都映射到表中的列名称。 您可以使用@Column批注覆盖此默认映射,如下所示:


@Entity
@Table(name="BOOKS")
public class Book {
   private String name;
   @Column(name="ISBN_NUMBER")
   private String isbn;
   ...
}

在此示例中,我们接受了name属性的默认映射,但为isbn属性指定了自定义映射。 name属性将映射到name列,但是isbn属性将映射到ISBN_NUMBER列。

@Column批注允许我们定义字段/列的其他属性,包括长度,是否可以为空,是否必须唯一,精度和小数位数(如果是十进制值),是否可插入和可更新以及等等。

指定主键

关系数据库表的要求之一是它必须包含主键或唯一标识数据库中特定行的键。 在JPA中,我们使用@Id批注将字段指定为表的主键。 主键必须是Java基本类型,基本包装(例如IntegerLongStringDateBigIntegerBigDecimal

在此示例中,我们将id属性(即Integer映射到BOOKS表中的ID列:


@Entity
@Table(name="BOOKS")
public class Book {
   @Id
   private Integer id;
   private String name;
   @Column(name="ISBN_NUMBER")
   private String isbn;
   ...
}

也可以将@Id注释与@Column注释结合使用,以覆盖主键的列名映射。

实体之间的关系

现在您知道了如何定义实体,让我们看看如何在实体之间创建关系。 JPA定义了四个用于定义实体的注释:

  • @OneToOne
  • @OneToMany
  • @ManyToOne
  • @ManyToMany

一对一关系

@OneToOne批注用于定义两个实体之间的一对一关系。 例如,您可能具有一个User实体,其中包含用户的名称,电子邮件和密码,但是您可能希望在单独的UserProfile实体中维护有关该用户的其他信息(例如年龄,性别和喜欢的颜色)。 @OneToOne注释有助于以这种方式分解数据和实体。

下面的User类具有一个UserProfile实例。 UserProfile映射到单个User实例。


@Entity
public class User {
   @Id
   private Integer id;
   private String email;
   private String name;
   private String password;
   @OneToOne(mappedBy="user")
   private UserProfile profile;
   ...
}

@Entity
public class UserProfile {
   @Id
   private Integer id;
   private int age;
   private String gender;
   private String favoriteColor;
   @OneToOne
   private User user;
   ...
}

JPA提供程序使用UserProfileuser字段将UserProfile映射到User 。 映射在@OneToOne批注中的mappedBy属性中指定。

一对多和多对一关系

@OneToMany@ManyToOne注释可促进同一关系的双方。 考虑一个示例,其中一Book只能有一个Author ,但一个Author可能有很多书。 Book实体将与Author定义一个@ManyToOne关系,而Author实体将与Book定义一个@OneToMany关系。


@Entity
public class Book {
    @Id
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name="AUTHOR_ID")
    private Author author;
    ...
}

@Entity
public class Author {
    @Id
    @GeneratedValue
    private Integer id;
    private String name;
    @OneToMany(mappedBy = "author")
    private List<Book> books = new ArrayList<>();
    ...
}

在这种情况下, Author类维护该Author编写的所有书籍的列表,而Book类维护对其单个作者的引用。 另外, @JoinColumn指定Book表中列的名称,以存储Author的ID。

多对多关系

最后, @ManyToMany注释促进了实体之间的多对多关系。 这是Book实体具有多个Author的情况:


@Entity
public class Book {
    @Id
    private Integer id;
    private String name;
    @ManyToMany
    @JoinTable(name="BOOK_AUTHORS",
    		   joinColumns=@JoinColumn(name="BOOK_ID"),
    		   inverseJoinColumns=@JoinColumn(name="AUTHOR_ID"))
    private Set<Author> authors = new HashSet<>();
    ...
}

@Entity
public class Author {
    @Id
    @GeneratedValue
    private Integer id;
    private String name;
    @ManyToMany(mappedBy = "author")
    private Set<Book> books = new HashSet<>();
    ...
}

在此示例中,我们创建一个具有两列的新表BOOK_AUTHORSBOOK_IDAUTHOR_ID 。 使用joinColumnsinverseJoinColumns属性可以告诉您的JPA框架如何以多对多关系映射这些类。 Author类中的@ManyToMany注释引用Book类中用于管理关系的字段。 即authors属性。

这是一个相当复杂的主题的快速演示。 在下一篇文章中,我们将进一步研究@JoinTable@JoinColumn批注。

使用EntityManager

EntityManager是在JPA中执行数据库交互的类。 它通过名为persistence.xml的配置文件初始化。 该文件位于CLASSPATHMETA-INF文件夹中,该文件夹通常打包在JAR或WAR文件中。 persistence.xml文件包含:

  • 名为“持久性单元”,它指定您正在使用的持久性框架,例如Hibernate或EclipseLink。
  • 属性的集合,指定如何连接到数据库以及持久性框架中的所有自定义项。
  • 项目中实体类的列表。

让我们来看一个例子。

配置EntityManager

首先,我们使用从Persistence类检索的EntityManagerFactory创建一个EntityManager


EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("Books");
EntityManager entityManager = entityManagerFactory.createEntityManager();

在这种情况下,我们创建了一个连接到“ Books”持久性单元的EntityManager ,我们已在persistence.xml文件中对其进行了配置。

EntityManager类定义我们的软件如何通过JPA实体与数据库进行交互。 以下是EntityManager使用的一些方法:

  • find通过其主键检索实体。
  • createQuery创建一个Query实例,该实例可用于从数据库中检索实体。
  • createNamedQuery加载一个持久化实体之一内@NamedQuery批注中定义的Query命名查询提供了一种干净的机制,用于在将执行查询的持久性类的定义中集中化JPA查询。
  • getTransaction定义要在数据库交互中使用的EntityTransaction 。 就像数据库事务一样,您通常将开始事务,执行操作,然后提交或回滚事务。 使用getTransaction()方法可以在EntityManager级别(而不是数据库getTransaction()访问此行为。
  • merge()将一个实体添加到持久性上下文中,以便在提交事务时,该实体将被持久化到数据库中。 使用merge() ,不管理对象。
  • persist将实体添加到持久性上下文中,以便在提交事务时将实体持久化到数据库中。 使用persist() ,将管理对象。
  • refresh从数据库刷新当前实体的状态。
  • flush将持久性上下文的状态与数据库同步。

不必担心一次集成所有这些方法。 您将通过直接使用EntityManager来了解它们,我们将在下一部分中做更多的工作。

翻译自: https://www.infoworld.com/article/3373652/java-persistence-with-jpa-and-hibernate-part-1-entities-and-relationships.html

jpa和hibernate

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值