只需用@ID注释JPA实体的ID字段,并允许DB关心其余的!在某些情况下,缺省值应该改变。在本文中,我们将看到更改ID生成策略会如何影响应用程序的性能。
根据JPA规范,Entity
是满足以下要求的Java类:
- 带注释
@Entity
注记 - 没有args构造函数。
- 不是最终的
- 具有带注释的ID字段(或多个字段)
@Id
如您所见,需要ID。那是为什么?
我们为什么要在JPA实体中使用ID呢?
JDBC和关系数据库不需要表的主键或唯一键。在使用JDBC时,我们使用自己的语言--原生SQL查询与数据库进行通信。若要获取数据集,开发人员将运行SELECT
语句,该语句返回相应的元组。要保存或更新数据,我们需要编写另一个INSERT
或UPDATE
声明。在应用程序到数据库级的通信中,应用程序中的对象与存储在数据库中的记录之间没有直接联系。通常,这种映射是作为业务逻辑的一部分手动管理的。
JPA采取了不同的方法。它引入了实体-Java对象,这些对象严格地与数据库中的记录绑定在一起。因此,JPA规范要求开发人员定义字段或一组字段,以在实体实例和特定DB记录之间建立一对一的关联。这样,开发人员就可以从数据库中获取JPA实体,使用它们并在以后保存它们,而无需调用任何JPA实体。INSERT
或UPDATE
陈述。这是允许开发人员主要关注业务逻辑的关键概念之一,而大多数样板操作是由JPA实现本身处理的,ID是此过程的重要部分。
注:ID不必映射到定义为表主键的列。我们需要将ID映射到唯一标识每一行的列。但是对于本文,我们将继续交替使用术语ID和主键。
ID类型:我们有什么
我们需要在实体中定义ID。我们有什么选择?
首先,我们可以定义一个“简单”或“复合”结构的ID。“简单”ID由实体中的单个字段表示,复合字段由一个单独的类表示,该类包含一组标识实体的字段。
通常,我们对JPA实体使用简单的ID。可以自动生成简单ID(代理ID),这是处理ID值的最常用方法。生成可以发生在数据库端(服务器端生成)或应用程序中(客户端生成)。这两种方法各有优缺点。
在本文中,我们将重点讨论服务器端生成的ID。为了简单起见,我们将使用Hibernate ORM作为所有示例的默认JPA实现,除非我们明确提到另一个ORM。
生成的ID-为什么我们要关心?
ID生成事件通常只发生一次--当我们将新实体保存到数据库时。因此,假设我们有一个不经常创建多个实体的应用程序(经验法则--假设每秒不超过100个实体),并且不与其他应用程序共享数据库。在这种情况下,理论上,我们可以使用任何ID生成策略。管理国家清单的应用程序就是一个很好的例子--我们并不经常创建新的国家。但是电能计量呢?如果我们有100米,每小时发送数据,我们必须每小时保存100个测量数据。基本上,我们每36秒就可以节省一次测量。看起来不太像。几千米呢?数以万计?如果我们决定每10分钟做一次测量呢?一个企业要花费多少钱来停止信息系统来改变ID生成策略?
在实践中,应用程序和业务一样趋向于增长和变化,这就是为什么必须选择适当的ID生成策略,以避免将来发生痛苦的迁移。我们将在这篇文章中提到很多性能,甚至我们的应用程序也不是新的Facebook或Twitter,它们还没有每秒节省数百万实体,我们应该提前考虑最合适的ID生成策略,以避免将来出现问题。
默认情况下世代是如何工作的
最简单的方法是在JPA实体中定义生成的ID,用@Id
和@GeneratedValue
注释。我们甚至不需要为@GeneratedValue
。默认情况下,您将得到一个正确生成的ID字段。
@Table(name = "pet")
@Entity
public class Pet {
@Id
@GeneratedValue
@Column(name = "id", nullable = false)
private Long id;
}
有两种类型的默认值:从一开始就不应更改的默认值和应该更改的默认值。默认值不会破坏应用程序,但是在生成ID的情况下,它们工作得好吗?让我们看看@GeneratedValue
默认参数值:
public @interface GeneratedValue {
GenerationType strategy() default AUTO;
String generator() default "";
}
正如我们所看到的,我们将生成策略参数设置为AUTO
。这意味着JPA提供者决定如何为ID生成一个唯一的值。让我们从我们可以使用的策略列表开始。
JPA标准除了描述AU