`
tomrose
  • 浏览: 147435 次
  • 来自: ...
社区版块
存档分类
最新评论

jpa 主建

阅读更多
将主键与 Java 持久性配合使用
作者:Sean Brydon 及 Smitha Kangath
状态:在 Early Access 版本阶段

问题描述
持久性实体需要主键。本文介绍了在开发使用 Java 持久性 API 的应用程序的模型层时使用主键的一些指南和提示。我们先看一下主键是如何定义的,然后介绍一些生成主键的策略。

解决方案
主键需要遵循一些指南。
简单或复合?
主键类型可以是 Java 基元类型(int、byte 和 long 等)、基元包装类型(Integer、Byte 和 Long 等)、java.lang.String、java.util.Date 或 java.sql.Date。除了选择类型外,应用程序开发者还必须选择是使用简单主键,还是使用复合主键。

简单主键涉及实体的单个持久性字段或属性。可以使用 @Id 标注来表示一个简单主键。使用 @Id 标注表示的实体字段(或属性)将映射到相应数据库表的主键上。下面的代码示例 1 说明了如何定义简单主键:

@Entity public class Item {
  ...
  //use default column mapping
  String itemId;

  @Id
  public String getItemId() {
    return itemId;
  }
...
}
代码示例 1:简单主键

复合主键可以对应单个也可以对应一组持久性字段,并且由主键类表示。复合键通常定义为包含几个表列的嵌入类。当相应数据库表的主键包含几个列时,复合键是非常有用的。复合键可以由 @EmbeddedId 或 @IdClass 标注进行定义。在使用 @EmbeddedId 标注时,表示复合键的类是由 @Embeddable 标注指定的嵌入类。请注意,复合键类必须是可序列化的,并且必须定义 equals 和 hashCode 方法。下面的代码示例 2 说明了如何使用 @EmbeddedId 标注来定义复合键。

@Embeddable public class ItemId implements Serializable {
    private String firstName;
    private String lastName;
    ...
  
}

@Entity public class Item implements Serializable {
    private ItemId id;
    @EmbeddedId public ItemId getId() {
        return id;
    }
    ...
}
代码示例 2:使用 @EmbeddedId 标注的复合主键

用于生成主键的策略
主键可以由数据库、容器或应用程序自身来生成。如果主键是由提供程序或数据库生成的,则称主键是自动生成的。
在应用程序中生成主键

此处的一个选择是,将数据固有的部分作为主键。在这种情况下,数据已包含主键,因此,不需要生成或指定主键,应用程序只需使用数据的主键即可。例如,表示美国纳税人的实体的社会保险号码。如果应用程序数据尚未包含主键,则在创建数据并将其存储到数据库中时,应用程序需要为数据指定主键。应用程序必须以编程方式创建和设置主键的值。一种完成此操作的方法是,创建一个 Id 表(类似于序列号)和一个映射到该表上的关联对象,并使用类似于 IdGenerator.getNextId() 的 API。另一种方法是只调用 System.currentTimeMillis()。切记,这些方法可能无法在群集环境中按预期方式工作。

让应用程序生成主键的一个优点是,您可以在数据库中永久保存数据之前了解该键。

自动生成主键

另一种选择是,自动生成 Id 并让提供程序或数据库设置该值。通过这种方式,应用程序开发者不需要编写任何 Id 生成逻辑。只需在 Id 上使用标注,然后把工作交给提供程序和数据库即可。

Java 持久性提供了一种以这种方式自动生成主键的机制(通过使用 @GeneratedValue 标注)。我们必须提供一种可选的 id 生成策略和可选的 id 生成器。@GeneratedValue 标注是与 @Id 标注结合使用的。

持久性提供程序可以使用多种生成策略来生成主键。生成策略可以是 TABLE、SEQUENCE、IDENTITY 或 AUTO 之一。

对于 IDENTITY 策略,数据库添加一个标识列并负责完成主键生成操作。此策略特定于数据库,并要求数据库支持 IDENTITY 列类型。因此,可能无法在数据库之间移植此策略。

对于 SEQUENCE 策略,持久性提供程序使用一个可以生成主键的数据库序列。此策略要求数据库支持 Sequence,因而可能无法在数据库之间进行移植。

TABLE 策略是指基于基本的数据库表来分配值。由于 TABLE 策略不基于任何特定于数据库的功能,因此,可以在数据库之间进行移植。

AUTO 是指持久性提供程序应该选取适当的策略。

SEQUENCE、IDENTITY 和 AUTO 策略不能在数据库之间进行移植。还要切记,AUTO、SEQUENCE 和 TABLE 策略可能无法在群集环境中正常工作。所有这三种策略都需要提供程序来完成某些操作。如果提供程序无法完成此类操作,则可能会导致数据不一致。在 IDENTITY 策略中,数据库不使用提供程序来完成操作,因而不会在群集环境中出现数据不一致。

被指定为一个 GeneratedValue 标注元素的 id 生成器必须用 SequenceGenerator 标注或 TableGenerator 标注进行声明,具体取决于生成策略是 SEQUENCE 还是 TABLE。可以在实体类或主键字段上声明这两种标注。生成器的范围是持久性单元。

让我们看一下,如何使用 TABLE 生成策略自动生成主键。通过使用表生成器,持久性提供程序使用数据库表来存储生成的 Id。一个实体将在表中单占一行。表具有主键名称列和值列。用于创建生成器表的 SQL 命令类似于:

CREATE TABLE ID_GEN(GEN_KEY VARCHAR(10) NOT NULL, GEN_VALUE INTEGER NOT NULL,primary key (GEN_KEY));

必须在此表中插入一行以作为生成器的种子。
INSERT INTO ID_GEN VALUES('ITEM_ID',101);

现在,假设有一个 Item 表,将项 id 用作主键,则生成的 Id 将从 102 开始。您必须在 Item 的持久性实体的 TableGenerator 标注中引用此表。该标注类似于:

  @TableGenerator(name="ID_GEN",
            table="ID_GEN",
            pkColumnName="GEN_KEY",
            valueColumnName="GEN_VALUE",
            pkColumnValue="ITEM_ID",
            allocationSize=1)
  @GeneratedValue(strategy=GenerationType.TABLE,generator="ID_GEN")
  @Id
  public int getItemID() {
      return itemID;
  }
  ...

一种常见的使用情况是,当前已有一个数据库,而需要为新插入的记录自动生成主键。如果现有主键是连续的类型,则可以实现此操作。

保留主键

所有实体必须有一个主键,这是第一次将实体永久保存到数据库时设置的。应用程序不应修改 Java 实体的主键值,也没有定义应用程序尝试修改主键值时的实际行为。如果应用程序确实需要修改主键,则应该先删除实体,然后使用新主键添加该实体,同时还要确保引用完整性。对于大多数情况,应用程序不需要修改主键。例如,使用自动生成的 id 时,应用程序甚至不需要设置它的值。由于实体包含不应该被应用程序代码修改的标识字段(或主键类),因此,在代码中设置一些保护措施以防止更改主键是非常有用的。一种方法是通过 Javadoc 对 setPK(...) 方法或类进行描述,向用户指明不要调用主键的 set 方法,以及不要直接访问主键字段以对其进行修改。然而,这不是一种自身起作用的方法。因为实体开发者总是希望使团队中的其他开发者能够方便、正确地使用该实体。例如,一个 Web 开发者在编写代码调用实体时,可能会无意中修改该实体的主键值。

请注意,除了访问实体字段和方法的应用程序代码外,容器和持久性提供程序也会访问实体。容器将通过字段或属性方法来访问实体,具体取决于应用程序代码所指定的方法。容器/提供程序必须访问主键值,因为它管理实体中的数据与数据库表中的数据之间的交互,并将它们保持同步以及执行其他操作。对于自动生成的 Id,容器还会访问实体,因为它将为主键分配值。因此,无论使用哪种机制来尝试并防止代码无意中修改主键,都必须考虑到容器需要访问实体的主键字段(或主键类)。

让我们简要介绍一种策略,它以一种使用户避免无意中修改主键的方式来开发实体 Bean。以下是实现此策略所涉及的五个步骤:

使用基于字段的标注。通过使用基于字段的标注,容器/提供程序将使用基于字段的访问来访问实体值。如果使用基于属性的访问,则必须为所有持久性字段(包括主键)公开 setter 和 getter 的 API,而此时您并不希望公开主键的 setter 方法。
在字段上使用包范围。这会降低主键字段对其他开发者的可见性,但容器仍然可以访问它们。持久性提供程序和容器应该能够访问它们,因此,不应将其设置为私有。
为其他字段提供 getter 和 setter 方法,和一个用于主键字段的 getter 方法。实体客户端可以访问这些方法。

制订一个策略,使开发者只能通过 getter 和 setter 方法来访问实体。

在主键的实体上设置一个私有的 setPK(...) 方法,使得只能在类内部访问它。这可以防止开发者在代码中使用实体时,调用 setPK(...) 方法并修改它的值。或者,干脆不为主键提供 setter 方法。
参考资料
Java 持久性 API 的 Javadoc
分享到:
评论

相关推荐

    04_JPA详解_第一个JPA实例与JPA主键生成策略.zip

    本压缩包文件"04_JPA详解_第一个JPA实例与JPA主键生成策略.zip"包含了关于如何在实际项目中运用JPA,以及理解JPA主键生成策略的详细教程。 ### JPA基础 1. **JPA简介**: JPA是Java EE的一部分,它提供了一套规范,...

    JPA主键策略(针对数据库自增字段重置后无效检查项)

    JPA主键策略详解 JPA(Java Persistence API)是一个Java标准,用于对象关系映射(ORM)。在JPA中,主键策略是指生成主键的机制,用于标识数据库表中的每一行记录。在本文中,我们将详细讨论JPA主键策略的类型、...

    04_传智播客JPA详解_第一个JPA实例与JPA主键生成策略

    【标题】"04_传智播客JPA详解_第一个JPA实例与JPA主键生成策略"涉及的关键知识点主要包括Java Persistence API (JPA)的基础应用、首个JPA实例的创建以及JPA主键生成策略的理解和配置。JPA是Java平台上的一个标准,...

    JPA学习笔记-EJB-03JPA主键生成策略总结

    ### JPA主键生成策略详解 #### 一、概述 持久化对象的主键生成机制在JPA(Java Persistence API)中占据着重要的位置。它不仅关乎数据的唯一标识符如何确定,还与数据的存储效率及应用逻辑紧密相关。JPA通过`@...

    JPA环境搭建及JPA实例与JPA主键生成策略

    **JPA主键生成策略** JPA提供了多种主键生成策略,以下是一些常见的策略: 1. **IDENTITY**:数据库负责生成主键,如MySQL的`AUTO_INCREMENT`。 2. **SEQUENCE**:使用数据库序列生成主键,适用于支持序列的数据库...

    JPA主键生成策略

    只要1分就可获得JPA主键生成策略,很全的哦

    JPA详解视频教程 第4讲 第一个JPA实例与JPA主键生成策略.avi

    JPA用于整合现有的ORM技术,可以简化现有Java EE和Java SE应用对象持久化的开发工作,实现ORM的统一。JPA详解视频教程 第4讲 第一个JPA实例与JPA主键生成策略.avi

    JPA_5_联合主键

    **JPA 联合主键详解** 在Java Persistence API(JPA)中,主键是用于唯一标识数据库表中每一行记录的关键字段。在某些情况下,一个实体可能需要多个字段来唯一标识其实例,这时就需要使用联合主键。本篇文章将深入...

    JPA联合主键

    **JPA联合主键详解** 在Java Persistence API (JPA) 中,主键是用于唯一标识实体的关键字段。在很多情况下,一个实体的主键可能不是由单一字段组成,而是由两个或更多个字段共同构成,这样的主键就被称为联合主键...

    JPA注解实现联合主键

    ### JPA注解实现联合主键 在关系型数据库中,单个字段作为主键的情况较为常见,但在某些场景下,我们需要使用多个字段共同作为主键来唯一标识表中的每一条记录,这就是所谓的“联合主键”。而在Java持久化框架...

    JPA 联合主键

    **JPA 联合主键详解** 在Java Persistence API(JPA)中,主键是用于唯一标识实体的关键字段。通常,一个实体可能只有一个主键字段,但有些情况下,为了实现唯一标识,可能需要使用两个或多个字段的组合,这就是...

    JPA中的联合主键

    在Java Persistence API (JPA) 中,联合主键(Composite Key)是指由两个或更多个字段共同组成的主键,这与单字段主键(Single Field Primary Key)相对。这种设计模式通常用于那些需要多个属性来唯一标识实体的情况...

    15_传智播客JPA详解_JPA中的联合主键

    本教程将聚焦于JPA中的一个关键概念——联合主键(Composite Key),这是处理多字段主键的一种方式。 联合主键是指在数据库表中,由两个或多个字段共同构成的唯一标识,这些字段的组合必须是唯一的。在JPA中,我们...

    传智播客JPA学习笔记.pdf

    第一个JPA实例与JPA主键生成策略** 在JPA中,主键的生成策略可以通过@Id注解和@GeneratedValue注解进行设置,如AUTO、IDENTITY、SEQUENCE、TABLE等,不同的策略对应不同的数据库系统主键生成方式。 **5. 日期_枚举...

    持久化类主键生成策略+例子

    ### JPA主键生成策略 1. **`GenerationType.AUTO`**:这是最常用的策略,具体的生成方式由数据库供应商决定,通常对应于自动增长字段,例如在MySQL中的`AUTO_INCREMENT`。 2. **`GenerationType.IDENTITY`**:此...

    JPA详解视频教程 第15讲 JPA中的联合主键.avi

    JPA用于整合现有的ORM技术,可以简化现有Java EE和Java SE应用对象持久化的开发工作,实现ORM的统一。JPA详解视频教程 第15讲 JPA中的联合主键.avi

    传智播客JPA学习笔记修改免积分版

    #### 五、JPA主键生成策略 - **自动生成策略**: - 如 AUTO, SEQUENCE, TABLE, IDENTITY 等,提供了多种方式来自动生成实体对象的主键值。 - **手动指定策略**: - 开发者可以根据需求选择合适的主键生成机制,如...

    Spring Data Jpa 复合主键的实现

    Spring Data Jpa 复合主键的实现 Spring Data Jpa 复合主键的实现是指在使用 Spring Data Jpa 进行数据持久化时,如何实现复合主键的机制。复合主键是指在一个表中,使用多个字段组合成一个唯一的主键。 在 Spring...

    真实项目中关于主键生成方式的剖析(JPA)

    本文主要探讨了在使用Java Persistence API (JPA) 和 Hibernate 框架时,如何处理主键的生成,特别是针对不同数据库系统的序列(sequence)机制。 首先,序列是一种在数据库中用于生成有序整数的机制,常被用作主键...

    使用表的id生成

    用户可能需要查看这些文件来深入理解JPA主键生成的实现细节。 综上所述,"使用表的id生成"这个主题涵盖了JPA中主键生成的基本原理、策略选择、源码解析以及可能的开发工具应用。通过学习和实践,开发者能够灵活地...

Global site tag (gtag.js) - Google Analytics