当前位置: 首页 > 工具软件 > ObjectDB > 使用案例 >

ObjectDB-JPA官方文档翻译之(一):JPA Primary Key

宋洲
2023-12-01

存储在数据库中的每个实体对象都有一个主键。

作为对象数据库,ObjectDB支持隐式对象ID,因此不需要显式定义的主键。但ObjectDB还支持显式的标准JPA主键,包括复合主键和自动序列值生成。这是ObjectDB的一个非常强大的特性,它在其他面向对象的数据库中是不存在的。

本页包含以下主题:

实体标识

自动主键

应用程序集主键

复合主键

嵌入的主键

获取主键

使用主键进行对象聚类

实体标识

数据库中的每个实体对象都通过其类型和主键的组合进行唯一标识(并且可以从数据库中检索)。每个实体类的主键值都是唯一的。但是,不同实体类的实例可以共享相同的主键值。

只有实体对象有主键。其他可持久类型的实例始终存储为包含其的实体对象的一部分,并且没有自己的独立标识。

自动主键 @Generated

默认情况下,主键是一个连续的64位数字(long),由objectdb为数据库中存储的每个新实体对象自动设置。数据库中第一个实体对象的主键为1,第二个实体对象的主键为2等。从数据库中删除实体对象时,不会回收主键值。

可以通过声明主键字段来访问实体的主键值:

@Entity
public class {
	@Id @Generated long id; //自动生成
}

@id注释将字段标记为主键字段。定义主键字段时,ObjectDB会自动将主键值注入该字段。

@generatedvalue注释指定由objectdb自动分配主键。自动值生成在“生成的值”部分中进行了详细讨论。

应用程序自行设定主键

如果实体的主键字段未标记为@GeneratedValue,则不会生成自动主键值,应用程序负责通过初始化主键字段来设置主键。在尝试持久化实体对象之前必须执行此操作。
由应用程序设置的主键字段可以是以下类型之一:

  • 基本类型:boolean byte short char int long folat double,及其各自的封装类型
  • String;Math类型:biginteger,bigdecimal; 日期时间:java.util.date、java.sql.date、java.sql.time、java.sql.timestamp。
  • 枚举类型
  • 用户自定义的@Entity类型
  • 复合主键@IdClass(“用户自定义的复合主键类的非限定名称”):复合主键由多个主键字段组成。每个主键字段必须是上面列出的支持类型之一。
复合主键类

当一个实体有多个主键字段时,JPA规范要求用户必须自定义一个特殊的ID类,规范如下:

  • Id类必须有一个public 的无参构造方法
  • Id类中的所有字段的类型及名词,必须在其所属@Entity类中的有完全相同的字段,且在@Entity类中的这样的字段前必须标注@Id
  • 必须重写hashCode()和equals()方法
    例如:
//主键类
Class ProjectId {
    int departmentId;
    long projectId;
    ...
}

//Entity类
@Entity @IdClass(ProjectId.class)
public class Project {
 	@Id int departmentId;
    @Id long projectId;
    ...
}

ObjectDB不强制定义ID类。但是,如果实体对象必须由其主键检索,则需要ID类。

可嵌入主键 @EmbeddedId

表示复合主键的另一种方法是使用可嵌入类,自定义一个可嵌入类需要对类做@Embeddable标注。然后在Entity类中定义一个此可嵌入类型的字段作为主键,并对此字段加@EmbeddedId标注

@Entity
public class Project {
    @EmbeddedId ProjectId id;
	...
}

@Embeddable
Class ProjectId {
    int departmentId;
    long projectId;
}

获取主键

JPA2提供了一种获取指定托管实体对象的对象ID(主键)的通用方法。例如:

persistenceUnitUtil=emf.getPersistenceUnitUtil();//从EntityManagerFactory获取PersistenceUnitUtil实例。

projectID=util.getIdentifier(project);

getIdentifier方法接受一个参数,一个托管实体对象,并返回主键。对于复合主键-返回ID类或可嵌入类的实例。

使用主键进行对象聚类

实体对象物理存储在数据库中,并按主键排序。有时,选择一个主键可以帮助以有效的方式对数据库中的实体对象进行集群。这在使用返回大型结果集的查询时特别有用。

例如,考虑一个实时系统,它检测来自不同传感器的事件并将详细信息存储在数据库中。每个事件都由一个事件实体对象表示,该对象包含时间、传感器ID和其他详细信息。假设检索指定时间段内指定传感器的所有事件的查询是常见的,并返回数千个事件对象。在这种情况下,以下主键可以显著提高查询运行性能:

@Entity
public class Event {
    @EmbeddedId EventId id;
     :
}

@Embeddable
Class EventId {
    int sensorId;
    Date time;
}

由于实体对象是按其主键在数据库中排序的,所以同一传感器在一段时间内的事件是连续存储的,可以通过访问最少数量的数据库页来收集。

另一方面,这样的主键需要更多的存储空间(尤其是当数据库中有许多对事件对象的引用时,因为对实体的引用包含主键值),并且在存储操作中效率较低。因此,必须考虑所有因素,可能需要一个基准来评估不同的备选方案,以便选择最佳解决方案。

 类似资料: