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 backing maps, indexes and other plug-ins.
When designing an entity schema, you must complete the
following tasks:
- Define the entities and their relationships.
- Configure the eXtreme Scale.
- Register the entities with the eXtreme Scale.
- Create applications that interact with the eXtreme Scale, entity manager,
and entities.
Entity schema configuration
An entity schema
is a set of entities and the relationships between the entities. In
an
eXtreme Scale with multiple
partitions, the following restrictions and options apply to entity
schemas:
- Each entity schema must have a single root defined. This is known
as the schema root.
- All the entities for a given schema must be in the same map set,
which means that all the entities that are reachable from a schema
root with key or non-key relationships must be defined in the same
map set as the schema root.
- Each entity can belong to only one entity schema.
- Each eXtreme Scale can
have multiple schemas.
Entities are registered with an
eXtreme Scale before it is initialized.
Each defined entity must be uniquely named and is automatically bound
to an
eXtreme Scale backing
map of the same name. The initialization method varies depending
on the configuration you are using:
Stand-alone eXtreme Scale
If you are
using a stand-alone
eXtreme Scale configuration,
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.
Entity class requirements
Entities are identified
by associating various metadata with a Java class.
The metadata can be specified using
Java Platform,
Standard Edition 5 annotations, an
entity metadata descriptor file, or a combination of annotations and
the descriptor file. Entity classes must meet the following criteria:
- Must have the @Entity annotation defined
or specified in the entity XML descriptor file.
- Must have a Public or Protected no-arg constructor.
- Must be a top-level class. Interfaces and enumerated types (enums)
are not valid entity classes.
- Must not use the final keyword.
- Must not use inheritance.
- Must be a unique name and type for each eXtreme Scale.
Entities all have a unique name and type. The name, if using
annotations, is the simple (short) name of the class by default, but
can be overridden using the name attribute of the
@Entity annotation.
Persistent attributes
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.
- Persistent fields
- Field-access entity instance variables are accessed directly from
the entity manager and clients. Fields that are marked with the transient
modifier or transient annotation are ignored. Persistent fields must
not have final or static modifiers.
- Persistent properties
- Property-access entities must adhere to the JavaBeans™ signature conventions for read
and write properties. Methods that do not follow JavaBeans conventions or have the Transient
annotation on the getter method are ignored. For a property of type T,
there must be a getter method: T getProperty() and
a setter method: void setProperty(T). For boolean
types, the getter method can be expressed as boolean isProperty().
Persistent properties must not have the static modifier.
- Supported attribute types
- The following persistent field and property types are supported:
- Java primitive types including
wrappers
- java.lang.String
- java.math.BigInteger
- java.math.BigDecimal
- java.util.Date
- java.util.Calendar
- java.sql.Date
- java.sql.Time
- java.sql.Timestamp
- byte[]
- java.lang.Byte[]
- char[]
- java.lang.Character[]
- enum
User serializable attribute types are supported but have performance,
query and change-detection limitations. Persistent data that cannot
be proxied, such as arrays and user serializable objects, must be
reassigned to the entity if altered.
Entity associations
Bi-directional and uni-directional
entity associations, or relationships between entities can be defined
as one-to-one, many-to-one, one-to-many and many-to-many. The entity
manager automatically resolves the entity relationships to the appropriate
key references when storing the entities in the
eXtreme Scale.
The eXtreme Scale 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 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. In the following example, we have 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 off the relationship. Because this association is
one-to-one, you must 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 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).
In the previous example, it is not practical
to have one address object per customer because many customers might
share an address or might have multiple addresses. This situation
is better solved using a many association:
@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 a to use the
targetEntity attribute
when generics are not available.
Primary keys
All entities must have a primary
key and can be a simple (single attribute) or composite (multiple
attribute) key. The key attributes are denoted using the Id annotation
or defined in the entity XML descriptor file. Key attributes have
the following requirements:
- The value of a primary key must not change.
- A primary key attribute should be one of the following types: Java primitive type and wrappers,
java.lang.String, java.util.Date or java.sql.Date.
- A primary key can contain any number of single valued associations.
The target entity of the primary key association must not have an
inverse association directly or indirectly to the source entity.
Composite primary keys can optionally define a primary key class.
An entity is associated with a primary key class using the
@IdClass annotation
or the defined in the entity xml descriptor file. An
@IdClass annotation
is useful when used in conjunction with the
EntityManager.find method.
Primary
key classes have the following requirements:
- The primary key class must have be public and have a public no-arg
constructor.
- The access type of the primary key class is determined by the
entity that declares the primary key class.
- If property-access, the properties of the primary key class must
be public or protected.
- The primary key fields or properties must match the key attribute
names and types defined in the referencing entity.
- Primary key classes must implement the equals and hashCode methods.
@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) {...}
}
Entity proxies and field interception
Entity
classes and mutable
supported
attribute types are extended by proxy classes for property-access
entities and bytecode-enhanced for
Java Development
Kit (JDK) 5 field-access entities.
All access to the entity, even by internal business methods and the
equals methods, must use the appropriate field or property access
methods.
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.
Attention: When using property-access entities, the equals method
should use the instanceof operator for comparing the current instance
to the input object. All introspection of the target object should
be through the object's properties and not the fields themselves as
the object instance will be the proxy.