ObjectGrid 可以具有任意数量的逻辑实体模式。 实体使用注释的 Java™ 类、XML 或 XML 和 Java 类的组合进行定义。 然后,定义的实体会向 eXtreme Scale 服务器注册,并绑定到 BackingMap、索引和其他插件。
本地 eXtreme Scale 配置
如果您正使用本地 ObjectGrid,那么可通过编程方式配置实体模式。在此方式中,可以使用 ObjectGrid.registerEntities 方法,以注册带注释的实体类或实体元数据描述符文件。分布式 eXtreme Scale 配置
如果您正使用分布式 eXtreme Scale 配置,那么必须为实体元数据描述符文件提供实体模式。有关更多详细信息,请参阅分布式环境中的实体管理器。
使用 Java 类文件、实体描述符 XML 文件或这两者来配置实体元数据。至少需要实体描述符 XML 确定哪些 eXtreme Scale BackingMap 将与实体关联。在带注释的 Java 类(实体元数据类)或实体描述符 XML 文件中,描述实体的持久属性以及此实体与其他实体的关系。实体元数据类(指定时)也由 EntityManager API 使用,以与数据网格中的数据交互。
eXtreme Scale 网格可以在不提供任何实体类的情况下进行定义。当服务器和客户机直接与底层映射中存储的元组数据交互时,这可能会有用。这些实体完全在实体描述符 XML 文件中进行定义,且称为无类实体。
当无法在服务器或客户机类路径中包含应用程序类时,无类实体有用。这些实体在实体元数据库描述符 XML 文件中进行定义,其中,实体的类名通过使用无类实体标识进行指定,格式为:@<entity identifier>。@ 符号将实体标识为无类,且用于映射实体之间的关联。请参阅“无类实体元数据”图,此图是实体元数据描述符 XML 文件(定义了两个无类实体)的示例。
如果 eXtreme Scale 服务器或客户机无权访问这些类,那么它们仍可以利用使用无类实体的 EntityManager API。常见用例包括以下用例:
如果客户机和服务器之间的实体元数据兼容,那么可以使用实体元数据类、XML 文件或这两者来创建实体元数据。
例如,下图中的“程序化实体类”与下一部分中的无类元数据代码兼容。
程序化实体类
@Entity
public class Employee {
@Id long serialNumber;
@Basic byte[] picture;
@Version int ver;
@ManyToOne(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
Department department;
}
@Entity
public static class Department {
@Id int number;
@Basic String name;
@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="department")
Collection<Employee> employees;
}
如上所述,无类实体完全在实体 XML 描述符文件中配置。基于类的实体使用 Java 字段、属性和注释定义其属性。因此,无类实体需要使用 <basic> 和 <id> 标记在实体 XML 描述符中定义键和属性结构。
Classless entity metadata
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://ibm.com/ws/projector/config/emd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ibm.com/ws/projector/config/emd ./emd.xsd">
<attributes>
<id name="serialNumber" type="long"/>
<basic name="firstName" type="java.lang.String"/>
<basic name="picture" type="[B"/>
<version name="ver" type="int"/>
<many-to-one
name="department"
target-entity="@Department"
fetch="EAGER"">
<cascade><cascade-persist/></cascade>
</many-to-one>
</attributes>
</entity>
<attributes>
<id name="number" type="int"/>
<basic name="name" type="java.lang.String"/>
<version name="ver" type="int"/>
<one-to-many
name="employees"
target-entity="@Employee"
fetch="LAZY"
mapped-by="department">
<cascade><cascade-all/></cascade>
</one-to-many>
</attributes>
</entity>
请注意,以上每个实体都具有 <id> 元素。无类实体必须具有一个或多个定义的 <id> 元素,或表示实体的键的单值关联。实体的字段由 <basic> 元素表示。<id>、<version> 和 <basic> 元素需要在无类实体中具有名称和类型。请参阅以下受支持属性类型部分,以获取有关受支持类型的详细信息。
客户机或实体管理器可通过使用字段(实例变量)或 Enterprise JavaBean 样式的属性访问器来访问实体的持久状态。每个实体必须定义基于字段或基于属性的访问。如果对类字段进行了注释,那么带注释的实体为基于字段访问的实体,如果对属性的 getter 方法进行注释,那么带注释的实体为基于属性访问的实体。不允许混合使用字段访问和属性访问。 如果无法自动确定类型,那么可以使用 @Entity 注释上的 accessType 属性或等效 XML 来确定访问类型。
使用对象的类名在实体描述符 XML 文件中表示可序列化属性。如果对象是一个数组,那么使用 Java 内部形式来表示数据类型。例如,如果属性数据类型为 java.lang.Byte[][],那么字符串表示为 [[Ljava.lang.Byte;
用户可序列化类型应遵循以下最佳实践:
eXtreme Scale 网格为数据高速缓存,不会强制实施引用完整性(如,数据库)。虽然关系允许级联存在且为子实体移除操作,但这不会检测对象的中断链接,或强制实施中断链接。移除子对象时,必须从父级移除对该对象的引用。
如果您在两个实体之间定义双向关联,那么必须确定关系所有者。在一对多或多对多的关联中,关系的多一方始终是所有者。如果无法自动确定所有权,那么必须指定注释的 mappedBy 属性或 XML 等效项。mappedBy 属性确定为关系所有者的目标实体中的字段。当具有多个类型和基数相同的属性时,此属性还帮助确定相关字段。单值关联
使用 @OneToOne 和 @ManyToOne 注释或等效 XML 属性表示一对一和多对一关联。 目标实体类型由属性类型确定。以下示例定义 Person 和 Address 之间的单向关联。 Customer 实体具有对一个 Address 实体的引用。在此情况下,关联也可以为多对一,这是因为没有反向关系。@Entity
public class Customer {
@Id id;
@OneToOne Address homeAddress;
}
@Entity
public class Address{
@Id id
@Basic String city;
}
要在
Customer 和 Address 类之间指定双向关系,请从 Address 类添加对 Customer 类的引用,并添加相应注释以标记关系的反向方。由于此关联是一对一关联,因此必须在 @OneToOne 注释上使用 mappedBy 属性来指定关系的所有者。@Entity
public class Address{
@Id id
@Basic String city;
@OneToOne(mappedBy="homeAddress") Customer customer;
}
集合值关联
使用 @OneToMany 和 @ManyToMany 注释或等效 XML 属性来表示一对多和多对多关联。使用 types: java.util.Collection、java.util.List 或 java.util.Set 表示所有多方关系。 目标实体类型通过 Collection、List 或 Set,或者在 @OneToMany 或 @ManyToMany 注释上显式使用 targetEntity 属性(或 XML 等效项)确定。@Entity
public class Customer {
@Id id;
@ManyToOne Address homeAddress;
@ManyToOne Address workAddress;
}
@Entity
public class Address{
@Id id
@Basic String city;
@OneToMany(mappedBy="homeAddress") Collection<Customer> homeCustomers;
@OneToMany(mappedBy="workAddress", targetEntity=Customer.class)
Collection workCustomers;
}
在此示例中,相同实体之间存在两种不同关系:Home 地址和 Work 地址关系。非通用集合用于 workCustomers 属性,以说明在通用项不可用时如何使用 targetEntity 属性。无类关联
无类实体关联在实体元数据描述符 XML 文件中进行定义,定义方式与基于类的关联的定义方式类似。唯一的差异在于,目标实体不是指向实际类,而是指向用于实体的类名的无类实体标识。
下面是一个示例:
<many-to-one name="department" target-entity="@Department" fetch="EAGER">
<cascade><cascade-all/></cascade>
</many-to-one>
<one-to-many name="employees" target-entity="@Employee" fetch="LAZY">
<cascade><cascade-all/></cascade>
</one-to-many>
@Entity
@IdClass(CustomerKey.class)
public class Customer {
@Id @ManyToOne Zone zone;
@Id int custId;
String
name; ...
}
@Entity
public class Zone{
@Id String zoneCode;
String
name;}
public class CustomerKey {
Zone zone;
int custId;
public int hashCode() {...}
public boolean equals(Object o) {...}
}
无类主键
无类实体需要具有属性 id=true 的 XML 文件中至少具有一个 <id> 元素或关联。 这两者的示例将类似如下:
<id name="serialNumber" type="int"/>
<many-to-one name="department" target-entity="@Department" id="true">
<cascade><cascade-all/></cascade>
</many-to-one>
使用代理和字段拦截器,以允许实体管理器跟踪实体的状态,确定实体是否已更改以及改善性能。