Un ObjectGrid peut posséder un nombre quelconque de schémas d'entité logiques. Les entités sont définies à l'aide de classes Java annotées, d'un XML ou d'une combinaison d'un XML et de classes Java. Les entités définies sont ensuite enregistrées sur un serveur eXtreme Scale et associées à BackingMaps, à des index et d'autres plug-in.
Configuration eXtreme Scale locale
Si vous utilisez un ObjectGrid local, vous pouvez configurer le schéma d'entité à l'aide d'un programme. Dans ce mode, vous pouvez utiliser les méthodes ObjectGrid.registerEntities pour enregistrer les classes d'entité annotées ou un fichier de descripteur de métadonnées d'entité.Configuration eXtreme Scale répartie
Si vous utilisez une configuration eXtreme Scale répartie, vous devez fournir un fichier de descripteur de métadonnées d'entité avec le schéma d'entité.Pour plus d'informations, reportez-vous à la rubrique Gestionnaire d'entités dans un environnement distribué.
Les métadonnées d'entité sont configurées à l'aide de fichiers de classe Java et/ou d'un fichier XML de descripteur d'entité. Le XML du descripteur d'entité au moins est requis pour identifier les mappes de sauvegarde eXtreme Scale associées à des entités. Les attributs persistants de l'entité et ses relations avec les autres entités sont décrits dans une classe Java annotée (classe de métadonnées d'entité) ou dans le fichier XML du descripteur d'entité. La classe de métadonnées d'entité, si elle est spécifiée, est également utilisée par l'API EntityManager pour interagir avec les données de la grille.
Une grille eXtreme Scale peut être définie sans fournir de classes d'entité. Cela peut être avantageux si le serveur et le client interagissent directement avec les données de nuplet stockées dans les mappes sous-jacentes. De telles entités sont intégralement définies dans le fichier XML du descripteur d'entité et sont appelées entités sans classe.
Les entités sans classe sont utiles s'il n'est pas possible d'inclure des classes d'application dans le chemin d'accès aux classes du serveur ou du client. De telles entités sont définies dans le fichier XML du descripteur de métadonnées d'entité, où le nom de classe de l'entité est spécifié à l'aide d'un identificateur d'entité sans classe de la forme suivante : @<identificateur d'entité>. Le symbole @ identifie l'entité comme sans classe et est utilisé pour les associations de mappage entre les entités. Pour un exemple de fichier XML de descripteur de métadonnées d'entité avec deux entités sans classe définies, voir la figure "Métadonnées d'entité sans classe".
Si un serveur ou un client eXtreme Scale n'a pas accès aux classes, il peut quand même utiliser l'API EntityManager à l'aide d'entités sans classe. Les cas d'utilisation courants sont les suivants :
Si les métadonnées d'entité sont compatibles entre le client et le serveur, elles peuvent être créées à l'aide de classes de métadonnées d'entité et/ou d'un fichier XML.
Par exemple, la "classe d'entité par programmation" de la figure ci-après est compatible avec le code des métadonnées sans classe de la section suivante.
Classe d'entité par
programmation
@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;
}
Comme indiqué précédemment, les entités sans classe sont configurées intégralement dans le fichier de descripteur XML d'entité. Les entités basées sur des classes définissent leurs attributs à l'aide d'annotations, de propriétés et de zones Java. Par conséquent, les entités sans classe doivent définir une structure de clés et d'attributs dans le descripteur XML d'entité à l'aide des balises <basic> et <id>.
Métadonnées
d'entité sans classe
<?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>
Notez que chaque entité ci-dessus contient un élément <id>. Une entité sans classe doit posséder un ou plusieurs éléments <id> ou une association à valeur unique qui représente la clé de l'entité. Les zones de l'entité sont représentées par des éléments <basic>. Les éléments <id>, <version> et <basic> requièrent un nom et un type dans les entités sans classe. Pour des détails sur les types pris en charge, reportez-vous à la section sur les types d'attribut pris en charge.
L'état persistant d'une entité est accessible par les clients et le gestionnaire d'entités à l'aide d'accesseurs aux zones (variables d'instance) ou aux propriété (style EJB). Chaque entité doit définir un accès par zone ou par propriété. Les entités annotées sont accessibles par des zones si les zones de la classe sont annotées ou accessibles par des propriétés si la méthode d'accès get de la propriété est annotée. Il n'est pas possible de mélanger les accès par zone et les accès par propriété. Si le type ne peut pas être déterminé automatiquement, l'attribut accessType de l'annotation @Entity ou le XML équivalent peut être utilisé pour identifier le type d'accès.
Les attributs sérialisables sont représentés dans le fichier XML du descripteur d'entité à l'aide du nom de classe de l'objet. Si l'objet correspond à un tableau, le type de données est représenté à l'aide du format Java interne. Par exemple, si un type de données d'attribut est java.lang.Byte[][], la représentation de la chaîne est la suivante : [[Ljava.lang.Byte;
Les types sérialisables par l'utilisateur doivent respecter les meilleures pratiques suivantes :
La grille eXtreme Scale est un cache de données et n'applique pas l'intégrité référentielle comme le fait une base de données. Les relations permettent les opérations de stockage et de suppression en cascade pour les entités enfant, mais elles ne détectent pas les liens rompus et ne les appliquent pas aux objets. Lors de la suppression d'un objet enfant, la référence à cet objet doit être supprimée du parent.
Si vous définissez une association bidirectionnelle entre deux entités, vous devez identifier le propriétaire de la relation. Dans une association to-many, la partie "many" de la relation est toujours la partie propriétaire. Si la propriété ne peut pas être déterminée automatiquement, l'attribut mappedBy de l'annotation ou son équivalent XML doit être spécifié. L'attribut mappedBy identifie la zone dans l'entité cible propriétaire de la relation. Cet attribut permet également d'identifier les zones en rapport lorsqu'il existe plusieurs attributs de même type et de même cardinalité.Associations à valeur unique
Les associations one-to-one et many-to-one sont dénotées à l'aide des annotations @OneToOne et @ManyToOne ou des attributs XML équivalents. Le type d'entité cible est déterminé par le type d'attribut. L'exemple ci-après définit une association unidirectionnelle entre Person et Address. L'entité Customer possède une référence à une entité Address. Dans ce cas, il peut également s'agir d'une association many-to-one car il n'existe pas de relation inverse.@Entity
public class Customer {
@Id id;
@OneToOne Address homeAddress;
}
@Entity
public class Address{
@Id id
@Basic String city;
}
Pour spécifier une relation bidirectionnelle entre les classes
Customer et Address, ajoutez une référence à la classe Customer
à partir de la classe Address et ajoutez l'annotation appropriée pour marquer
la partir inverse de la relation. Comme il s'agit d'une association
one-to-one, vous devez spécifier un propriétaire de la relation en utilisant
l'attribut mappedBy sur l'annotation @OneToOne.@Entity
public class Address{
@Id id
@Basic String city;
@OneToOne(mappedBy="homeAddress") Customer customer;
}
Associations évaluées par des collections
Les associations one-to-one et many-to-many sont dénotées à l'aide des annotations @OneToMany et @ManyToMany ou des attributs XML équivalents. Toutes les relations "many" sont représentées à l'aide des types suivants : java.util.Collection, java.util.List ou java.util.Set. Le type d'entité cible est déterminé par le type générique de la collection, de la liste ou de l'ensemble ou explicitement en utilisant l'attribut targetEntity sur l'annotation @OneToMany ou @ManyToMany (ou son équivalent 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;
}
Dans cet exemple, il existe deux relations entre les mêmes entités
: une relation d'adresse entre Home et Work. Une collection non générique est
utilisée pour l'attribut workCustomers afin
d'illustrer l'utilisation de l'attribut targetEntity
lorsqu'aucun générique n'est disponible.Associations sans classe
Les associations d'entités sans classe sont définies dans le fichier XML du descripteur de métadonnées d'entité, de la même manière que les associations basées sur des classes. Toutefois, l'entité cible ne pointe pas vers une classe réelle, mais vers un identificateur d'entité sans classe utilisé pour le nom de classe de l'entité.
Voici un exemple :
<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) {...}
}
Clés primaires sans classe
Les entités sans classe doivent contenir au moins un élément <id> ou une association dans le fichier XML avec l'attribut id=true. Voici un exemple de ces deux cas de figure :
<id name="serialNumber" type="int"/>
<many-to-one name="department" target-entity="@Department" id="true">
<cascade><cascade-all/></cascade>
</many-to-one>
Les proxys et les intercepteurs de zone sont utilisés pour permettre au gestionnaire d'entités de rechercher l'état de l'entité, de déterminer si l'entité a été modifiée et d'améliorer les performances. Les intercepteurs de zone ne sont disponibles que sur les plateformes Java SE 5 si l'agent d'instrumentation des entités est configuré.