An ObjectGrid can have any number of logical entity schemas. Entities are defined using annotated Java™ classes, XML, or a combination of both XML and Java classes. Defined entities are then registered with an eXtreme Scale server and bound to BackingMaps, indexes and other plug-ins.
Local eXtreme Scale configuration
If you are using a local ObjectGrid, you can programmatically configure the entity schema. In this mode, you can use the ObjectGrid.registerEntities methods to register annotated entity classes or an entity metadata descriptor file.Distributed eXtreme Scale configuration
If you are using a distributed eXtreme Scale configuration, you must provide an entity metadata descriptor file with the entity schema.For more details, see EntityManager in a distributed environment.
Entity metadata is configured using Java class files, an entity descriptor XML file or both. At minimum, the entity descriptor XML is required to identify which eXtreme Scale BackingMaps are to be associated with entities. The persistent attributes of the entity and its relationships to other entities are described in either an annotated Java class (entity metadata class) or the entity descriptor XML file. The entity metadata class, when specified, is also used by the EntityManager API to interact with the data in the grid.
An eXtreme Scale grid can be defined without providing any entity classes. This can be beneficial when the server and client are interacting directly with the tuple data stored in the underlying maps. Such entities are defined completely in the entity descriptor XML file and are referred to as classless entities.
Classless entities are useful when it is not possible to include application classes in the server or client classpath. Such entities are defined in the entity metadata descriptor XML file, where the class name of the entity is specified using a classless entity identifier in the form: @<entity identifier>. The @ symbol identifies the entity as classless and is used for mapping associations between entities. See the "Classless entity metadata" figure an example of an entity metadata descriptor XML file with two classless entities defined.
If an eXtreme Scale server or client does not have access to the classes, either can still use the EntityManager API using classless entities. Common use cases include the following:
If the entity metadata is compatible between the client and server, entity metadata can be created using entity metadata classes, an XML file, or both.
For example, the "Programmatic entity class" in the following figure is compatible with the classless metadata code in the next section.
Programmatic entity class @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; }
As previously mentioned, classless entities are configured completely in the entity XML descriptor file. Class-based entities define their attributes using Java fields, properties and annotations. So classless entities need to define key and attribute structure in the entity XML descriptor with the <basic> and <id> tags.
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"> <entity class-name="@Employee" name="Employee"> <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> <entity class-name="@Department" name="Department" > <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>
Note that each entity above has an <id> element. A classless entity must have either one or more of an <id> element defined, or a single-valued association that represents the key for the entity. The fields of the entity are represented by <basic> elements. The <id>, <version>, and <basic> elements require a name and type in classless entities. See the following supported attribute types section for details on supported types.
The persistent state of an entity is accessed by clients and the entity manager by using either fields (instance variables) or Enterprise JavaBeans-style property accessors. Each entity must define either field- or property-based access. Annotated entities are field-access if the class fields are annotated and are property-access if the getter method of the property is annotated. A mixture of field- and property-access is not allowed. If the type cannot be automatically determined, the accessType attribute on the @Entity annotation or equivalent XML can be used to identify the access type.
Serializable attributes are represented in the entity descriptor XML file using the class name of the object. If the object is an array, the data type is represented using the Java internal form. For example, if an attribute data type is java.lang.Byte[][], the string representation is [[Ljava.lang.Byte;
User serializable types should adhere to the following best practices:
The eXtreme Scale grid is a data cache and does not enforce referential integrity like a database. Although relationships allow cascading persist and remove operations for child entities, it does not detect or enforce broken links to objects. When removing a child object, the reference to that object must be removed from the parent.
If you define a bi-directional association between two entities, you must identify the owner of the relationship. In a to-many association, the many side of the relationship is always the owning side. If ownership cannot be determined automatically, then the mappedBy attribute of the annotation, or XML equivalent, must be specified. The mappedBy attribute identifies the field in the target entity that is the owner of the relationship. This attribute also helps identify the related fields when there are multiple attributes of the same type and cardinality.Single-valued associations
One-to-one and many-to-one associations are denoted using the @OneToOne and @ManyToOne annotations or equivalent XML attributes. The target entity type is determined by the attribute type. The following example defines a uni-directional association between Person and Address. The Customer entity has a reference to one Address entity. In this case, the association could also be many-to-one since there is no inverse relationship.@Entity public class Customer { @Id id; @OneToOne Address homeAddress; } @Entity public class Address{ @Id id @Basic String city; }To specify a bi-directional relationship between the Customer and Address classes, add a reference to the Customer class from the Address class and add the appropriate annotation to mark the inverse side of the relationship. Because this association is one-to-one, you have to specify an owner of the relationship using the mappedBy attribute on the @OneToOne annotation.
@Entity public class Address{ @Id id @Basic String city; @OneToOne(mappedBy="homeAddress") Customer customer; }
Collection-valued associations
One-to-many and many-to-many associations are denoted using the @OneToMany and @ManyToMany annotations or equivalent XML attributes. All many relationships are represented using the types: java.util.Collection, java.util.List or java.util.Set. The target entity type is determined by the generic type of the Collection, List or Set or explicitly using the targetEntity attribute on the @OneToMany or @ManyToMany annotation (or XML equivalent).@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; }In this example, two different relationships exist between the same entities: a Home and Work address relationship. A non-generic Collection is used for the workCustomers attribute to demonstrate how to use the targetEntity attribute when generics are not available.
Classless associations
Classless entity associations are defined in the entity metadata descriptor XML file similar to how class-based associations are defined. The only difference is that instead of the target entity pointing to an actual class, it points to the classless entity identifier used for the class name of the entity.
An example follows:
<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) {...} }
Classless primary keys
Classless entities are required to either have at least one <id> element or an association in the XML file with the attribute id=true. An example of both would look like the following:
<id name="serialNumber" type="int"/> <many-to-one name="department" target-entity="@Department" id="true"> <cascade><cascade-all/></cascade> </many-to-one>
Proxies and field interceptors are used to allow the entity manager to track the state of the entity, determine if the entity has changed, and improve performance. Field interceptors are only available on Java SE 5 platforms when the entity instrumentation agent is configured.