Um ObjectGrid pode ter inúmeros esquemas de entidade lógicos. As entidades são definidas usando as classes Java anotadas, o XML ou uma combinação de classes XML e Java. Entidades definidas são registradas com um servidor eXtreme Scale e ligadas a BackingMaps, índices e outros plug-ins.
Configuração do eXtreme Scale local
Se estiver utilizando um ObjectGrid local, será possível configurar programaticamente o esquema de entidade. Neste modo, é possível utilizar os métodos ObjectGrid.registerEntities para registrar classes de entidade anotadas ou um arquivo descritor de metadados.Configuração do eXtreme Scale distribuída
Se você estiver utilizando uma configuração do eXtreme Scale distribuída, é necessário fornecer um arquivo descritor de metadados da entidade com o esquema de entidade.Para obter detalhes adicionais, consulte Entity Manager em um Ambiente Distribuído.
Os metadados de entidade são configurados com o uso de arquivos de classe Java, um XML do descritor de entidade ou ambos. No mínimo, o XML do descritor de entidade é requerido para identificar quais BackingMaps do eXtreme Scale devem ser associados às entidades. Os atributos persistentes da entidade e seus relacionamentos com outras entidades são descritos em uma classe Java anotada (classe de metadados da entidade) ou arquivo XML do descritor de entidade. A classe de metadados da entidade, quando especificada, também é utilizada pela API EntityManager para interagir com dados na grade.
Uma grade do eXtreme Scale pode ser definida sem fornecer quaisquer classes de entidade. Isso pode ser benéfico quando o servidor e o cliente estiverem interagindo diretamente com os dados da tupla armazenados nos mapas subjacentes. Tais entidades são definidas completamente no arquivo XML do descritor de entidade e são referidas como entidades sem classe.
As entidades sem classe são úteis quando não é possível incluir classes de aplicativo no caminho de classe do servidor ou do cliente. Tais entidades são definidas no arquivo XML do descritor de entidade, onde o nome da classe da entidade é especificado utilizando um identificador de entidade sem classe no formato: @<identificador de entidade>. O símbolo @ identifica a entidade como sem classe e é utilizado para mapear associações entre entidades. Consulte a figura "Metadados da Entidade sem Classe" para ver um exemplo de um arquivo XML do descritor de metadados da entidade com duas entidades sem classe definidas.
Se um cliente ou servidor eXtreme Scale não tiver acesso às classes, eles poderão utilizar a API EntityManager utilizando as entidades sem classes. Casos de uso comuns incluem o seguinte:
Se os metadados da entidade forem compatíveis entre cliente e servidor, eles poderão ser criados utilizando classes de metadados da entidade, um arquivo XML ou ambos.
Por exemplo, a "Classe de Entidade Programática" na figura a seguir é compatível com o código de metadados sem classe na próxima seção.
Classe de entidade programática
@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;
}
Conforme mencionado anteriormente, as entidades sem classe são configuradas completamente no arquivo descritor XML da entidade. As entidades baseadas em classe definem seus atributos utilizando campos, propriedades e anotações Java. Portanto, as entidades sem classe precisam definir a estrutura de chave e atributo no descritor XML da entidade com as tags <basic> e <id>.
Metadados
da entidade sem 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>
Observe que cada entidade acima tem um elemento <id>. Uma entidade sem classe deve ter um ou mais de um elemento <id> definido, ou uma associação com valor único que represente a chave para a entidade. Os campos da entidade são representados pelos elementos <basic>. Os elementos <id>, <version> e <basic> requerem um nome e um tipo nas entidades sem classe. Consulte a seguinte seção de tipos de atributo suportados para obter detalhes sobre os tipos suportados.
O estado persistente de uma entidade é acessado por cliente e o entity manager utilizando qualquer um dos campos (variáveis de instância) ou acessores de propriedade do estilo Enterprise JavaBeans. Cada entidade deve definir um acesso baseado em campo ou em propriedade. Entidades anotadas são field-access se os campos de classe são anotados e property-access se o método getter da propriedade é anotada. Uma mistura de acesso por campo e acesso por propriedade não é permitida. Se o tipo não puder ser automaticamente determinado, o atributo accessType na anotação @Entity ou XML equivalente pode ser utilizado para identificar o tipo de acesso.
Os atributos serializáveis são representados no arquivo XML do descritor de entidade utilizando o nome de classe do objeto. Se o objeto for uma matriz, o tipo de dado será representado utilizando a forma interna Java. Por exemplo, se um tipo de dado de atributo for java.lang.Byte[][], a representação de cadeia será [[Ljava.lang.Byte;
Os tipos serializáveis de usuários devem obedecer às seguintes boas práticas:
A grade do eXtreme Scale é um cache de dados e não força integridade referencial como um banco de dados. Embora os relacionamentos permitam persistência em cascata e removam operações para entidades-filhas, eles não detectam ou impões links quebrados em objetos. Quando remover um objeto-filho, a referência a esse objeto deve ser removida do pai.
Se você definir uma associação bidirecional entre duas entidades, será preciso definir o proprietário do relacionamento. Em uma associação para-muitos, o lado muitos do relacionamento é sempre o lado do proprietário. Se a propriedade não puder ser determinada automaticamente, então, o atributo mappedBy da anotação ou equivalente XML, deve ser especificado. O atributo mappedBy identifica o campo na entidade de destino que é a proprietária do relacionamento. Este atributo também ajuda a identificar os campos relacionados quando há vários atributos do mesmo tipo e cardinalidade.Associações com valor único
Associações um-para-um e muitos-para-um são indicadas utilizando anotações @OneToOne e @ManyToOne ou atributos XML equivalentes. O tipo de entidade de destino é determinado pelo tipo de atributo. O exemplo a seguir define uma associação unidirecional entre Person e Address.s A entidade Cliente tem uma referência a uma entidade Endereço. Nesse caso, a associação poderia também ser de muitos-para-um, já que não há relacionamento inverso.@Entity
public class Customer {
@Id id;
@OneToOne Address homeAddress;
}
@Entity
public class Address{
@Id id
@Basic String city;
}
Para especificar um relacionamento bidirecional entre as
classes Customer e Address, inclua uma referência à classe Customer a
partir da classe Address e inclua a anotação apropriada para marcar o
lado inverso do relacionamento. Como essa associação é um-para-um,
você precisa especificar um proprietário do relacionamento utilizando
o atributo mappedBy na anotação @OneToOne.@Entity
public class Address{
@Id id
@Basic String city;
@OneToOne(mappedBy="homeAddress") Customer customer;
}
Associações com valor de coleta
Associações um-para-muitos e muitos-para-muitos são denotadas utilizando as anotações @OneToMany e @ManyToMany ou atributos XML XML equivalente. Todos os relacionamentos muito são representados utilizando os tipos: java.util.Collection, java.util.List ou java.util.Set. O tipo de entidade de destino é determinado pelo tipo genérico de Collection, List ou Set ou explicitamente utilizando atributo targetEntity na anotação @OneToMany ou @ManyToMany (ou XML equivalente).@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;
}
Neste exemplo, existem dois diferentes relacionamentos entre as
mesmas entidades: um relacionamento de endereços Home e Work. Uma
Collection não genérica é utilizada para o atributo
workCustomers para demonstrar como utilizar o
atributo targetEntity quando genéricos não
estiverem disponíveis.Associações sem classe
As associações de entidade sem classe são definidas no arquivo XML do descritor de metadados da entidade de forma semelhante ao modo como as associações baseadas em classe são definidas. A única diferença é que em vez de a entidade de destino apontar para uma classe real, ela aponta para o identificador da entidade sem classe utilizado para o nome de classe da entidade.
Este é um exemplo:
<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) {...}
}
Chaves primárias sem classe
Entidades sem classe devem ter pelo menos um elemento <id> ou uma associação no arquivo XML com o atributo id=true. Um exemplo de ambos seria semelhante ao seguinte:
<id name="serialNumber" type="int"/>
<many-to-one name="department" target-entity="@Department"
id="true">
<cascade><cascade-all/></cascade>
</many-to-one>
Os proxies e interceptores de campo são utilizados para permitir que o entity manager controle o estado da entidade, determine se a entidade foi alterada e aprimore o desempenho. Os interceptores de campo estão disponíveis apenas em plataformas Java SE 5 quando o agente de instrumentação da entidade é configurado.