O Google Code é oferecido em: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
Salvar um objeto de dados JDO no armazenamento de dados é uma simples questão de chamar o método makePersistent() da instância PersistenceManager. A implementação JDO do Google App Engine usa o campo da chave principal do objeto para controlar qual entidade do armazenamento de dados corresponde ao objeto de dados, e pode gerar chaves para novos objetos automaticamente. Você pode usar as chaves para recuperar rapidamente as entidades e pode construir chaves a partir de valores conhecidos (como IDs de conta).
Para armazenar um objeto de dados simples no armazenamento de dados, você chama o método makePersistent() do PersistenceManager, passando-o para a instância.
PersistenceManager pm = PMF.get().getPersistenceManager();
Employee e = new Employee("Alfred", "Smith", new Date());
try {
pm.makePersistent(e);
} finally {
pm.close();
}
A chamada para makePersistent() é síncrona e não retorna até que o objeto seja salvo e os índices sejam atualizados.
Para salvar diversos objetos na JDO, chame o método makePersistentAll(...) com uma coleção de objetos. Na versão atual, isso é implementado de forma parecida com uma série de chamadas para makePersistent(). Em uma versão futura, esse método executará com mais eficiência chamadas em lote para o armazenamento de dados.
Observação: Se qualquer um dos campos persistentes do objeto de dados for referência a outros objetos de dados persistentes, e qualquer um desses objetos nunca tiver sido salvo nem alterado desde que foi carregado, os objetos referenciados também serão salvos no armazenamento de dados. Consulte Relacionamentos.
Toda entidade tem uma chave exclusiva com relação a todas as entidades no Google App Engine. Uma chave completa inclui diversas informações, incluindo o ID do aplicativo, o tipo e um ID da entidade. As chaves também contêm informações sobre os grupos de entidade. Consulte Transações para obter mais informações.
A chave de um objeto é armazenada em um campo na instância. Você identifica o campo da chave principal usando a anotação @PrimaryKey.
O aplicativo pode fornecer a parte do ID da chave como uma string quando o objeto é criado, ou pode permitir que o armazenamento de dados gere um ID numérico automaticamente. A chave completa deve ser exclusiva em todas as entidades no armazenamento de dados. Em outras palavras, um objeto deve ter um ID exclusivo em todos os objetos do mesmo tipo e com o mesmo pai do grupo de entidades (se houver). Você seleciona o comportamento desejado da chave usando o tipo do campo e as anotações.
Se a classe for usada como uma classe "filha" em um relacionamento, o campo da chave deverá ser de um tipo capaz de representar um pai do grupo de entidades: uma instância de Key ou valor de Key codificado como uma string. Consulte Transações para obter mais informações sobre grupos de entidades e Relacionamentos para obter mais informações sobre relacionamentos.
Dica: Se o aplicativo criar um novo objeto e fornecer a ele o mesmo ID de string de outro objeto do mesmo tipo (e o mesmo pai do grupo de entidades), a gravação do novo objeto substituirá o outro objeto no armazenamento de dados. Para detectar se um ID de string já está sendo usado antes de criar um novo objeto, use uma transação para tentar obter uma entidade com um determinado ID, e crie um caso ele não exista. Consulte Transações.
Há 4 tipos de campos de chave principal:
Um número inteiro long (java.lang.Long), o ID de uma entidade gerado automaticamente pelo armazenamento de dados. É utilizado para objetos sem pais de grupo de entidades cujos IDs devem ser gerados automaticamente pelo armazenamento de dados. O campo de chave long de uma instância é preenchido quando a instância é salva.
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
// ...
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
Uma string (java.lang.String), o ID de uma entidade ("nome da chave") fornecido pelo aplicativo quando o objeto é criado. É utilizado para objetos sem pais de grupo de entidades cujos IDs devem ser fornecidos pelo aplicativo. O aplicativo define esse campo com o ID desejado antes de salvar.
import javax.jdo.annotations.PrimaryKey;
// ...
@PrimaryKey
private String name;
Uma instância de Key (com.google.appengine.api.datastore.Key). O valor da chave inclui a chave do pai do grupo de entidades (se houver) e o ID da string atribuído pelo aplicativo ou o ID numérico gerado pelo sistema. Para criar o objeto com um ID de string atribuído pelo aplicativo, crie o valor de Key com o ID e defina o campo com o valor. Para criar o objeto com um ID numérico atribuído pelo sistema, deixe o campo da chave nulo (para obter informações sobre como usar pais do grupo de entidades, consulte Transações).
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
// ...
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
public void setKey(Key key) {
this.key = key;
}
O aplicativo pode criar uma instância de Key usando a classe KeyFactory:
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
// ...
Key key = KeyFactory.createKey(Employee.class.getSimpleName(), "Alfred.Smith@example.com");
Employee e = new Employee();
e.setKey(key);
pm.makePersistent(e);
Parecido com Key, mas o valor é um formato de string codificada da chave. As chaves de string codificada permitem que você crie o seu aplicativo de uma maneira portátil e ainda aproveite a vantagem dos grupos de entidade do armazenamento de dados do Google App Engine.
import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
// ...
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String encodedKey;
O aplicativo pode preencher esse valor antes de salvar usando uma chave com um nome, ou pode deixar o campo nulo. Se o campo da chave codificada for nulo, o campo será preenchido com uma chave gerada pelo sistema quando o objeto for salvo.
As instâncias de Key podem ser convertidas para a representação da string codificada (e a partir dela) usando os métodos do KeyFactory keyToString() e stringToKey().
Ao usar strings de chave codificada, você pode fornecer acesso à string ou ao ID numérico de um objeto com um campo adicional:
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
private String encodedKey;
@Extension(vendorName="datanucleus", key="gae.pk-name", value="true")
private String keyName;
// OR:
@Extension(vendorName="datanucleus", key="gae.pk-id", value="true")
private Long keyId;
Um campo "gae.pk-name" pode ser definido com um nome de chave antes de salvar o objeto. Quando o objeto é salvo, o campo da chave codificada é preenchido com a chave completa que inclui o nome da chave. Seu tipo deve ser String.
Um campo "gae.pk-id" é preenchido quando o objeto é salvo e não pode ser modificado. Seu tipo deve ser Long.
Quando um novo objeto com uma chave gerada (um campo de chave usando valueStrategy = IdGeneratorStrategy.IDENTITY) é criado, seu valor de chave inicial é null. O campo da chave é preenchido quando o objeto é gravado no armazenamento de dados. Se você estiver usando uma transação, o objeto será gravado quando a transação for realizada. Caso contrário, o objeto será gravado quando o método makePersistent() for chamado, se o objeto estiver sendo criado, ou quando o método close() da instância PersistenceManager for chamado, se o objeto estiver sendo atualizado.
Se o aplicativo conhecer todos os elementos da chave completa da entidade, ele poderá criar o objeto Key correspondente sem o objeto.
Para uma chave de uma entidade sem um pai do grupo de entidades, você pode usar o método estático createKey() da classe KeyFactory. Esse método usa um tipo (o nome simples da classe), um ID de string atribuído pelo aplicativo ou um ID numérico atribuído pelo sistema, e retorna um objeto Key. Por exemplo, para recriar a chave de uma entidade do tipo "Employee" com o nome de chave "Alfred.Smith@example.com" (sem pai do grupo de entidades):
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
// ...
Key k = KeyFactory.createKey(Employee.class.getSimpleName(), "Alfred.Smith@example.com");
Para recriar uma chave de uma entidade do tipo "Employee" com um ID numérico 52234 atribuído pelo sistema (sem pai do grupo de entidades):
Key k = KeyFactory.createKey(Employee.class.getSimpleName(), 52234);
As chaves podem ser convertidas para uma representação de string (e a partir dela) usando os métodos keyToString() e stringToKey() da classe KeyFactory, respectivamente. Observe que isso é diferente do método toString() da classe Key, que retorna um valor legível adequado para depuração.
Para uma chave de uma entidade com um pai do grupo de entidades, você pode usar a classe KeyFactory.Builder:
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
// ...
Key k = new KeyFactory.Builder(Employee.class.getSimpleName(), 52234).addChild(ExpenseReport.class.getSimpleName(), "A23Z79").getKey();
O método addChild() da instância Builder retorna o Builder, de modo que você possa encadear as chamadas para adicionar cada elemento do caminho da chave. Para obter o valor completo de Key de um determinado builder, você pode chamar o método getKey() da instância Builder.
Para obter mais informações sobre grupos de entidades, consulte Transações.
Para recuperar um determinado objeto de acordo com a sua chave, use o método getObjectById() do PersistenceManager. Esse método usa a classe do objeto e a chave:
Key k = KeyFactory.createKey(Employee.class.getSimpleName(), "Alfred.Smith@example.com");
Employee e = pm.getObjectById(Employee.class, k);
Se a classe usar um campo de chave que é um ID de string não codificada (String) ou um ID numérico (Long), getObjectByID() poderá usar o valor simples como parâmetro:
Employee e = pm.getObjectById(Employee.class, "Alfred.Smith@example.com");
O argumento da chave pode ser qualquer um dos tipos de campo de chave suportados (ID de string, ID numérico, valor de Key, string de chave codificada) e pode ser um tipo diferente do campo de chave na classe. O Google App Engine precisa derivar a chave completa a partir do nome da classe e do valor fornecido. Os IDs de string e os IDs numéricos são exclusivos, por isso uma chamada usando um ID numérico nunca retornará uma entidade com um ID de string. Se um valor de Key ou string de chave codificada for usado, a chave deverá fazer referência a um entidade cujo tipo seja representado pela classe.
Uma forma de atualizar um objeto com JDO é obter o objeto e modificá-lo enquanto o PersistenceManager que retornou o objeto ainda esteja aberto. As alterações persistem quando o PersistenceManager é fechado. Por exemplo:
public void updateEmployeeTitle(User user, String newTitle) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Employee e = pm.getObjectById(Employee.class, user.getEmail());
if (titleChangeIsAuthorized(e, newTitle) {
e.setTitle(newTitle);
} else {
throw new UnauthorizedTitleChangeException(e, newTitle);
}
} finally {
pm.close();
}
}
Como a instância Employee foi retornada pelo PersistenceManager, este tem conhecimento de qualquer modificação feita nos campos Persistent na instância Employee e atualiza automaticamente o armazenamento de dados com essas modificações quando o PersistenceManager é fechado. Ele sabe disso porque a instância Employee está "anexada" ao PersistenceManager.
Você pode modificar um objeto após o PersistenceManager ter sido fechado declarando a classe como "detachable". Para fazer isso, adicione o atributo detachable à anotação @PersistenceCapable:
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class Employee {
// ...
}
Agora você pode ler e gravar os campos de um objeto Employee após o PersistenceManager que o carregou ter sido fechado. O exemplo a seguir ilustra como um objeto desanexado pode ser útil:
public Employee getEmployee(User user) {
PersistenceManager pm = PMF.get().getPersistenceManager();
pm.setDetachAllOnCommit(true);
try {
e = pm.getObjectById(Employee.class, "Alfred.Smith@example.com");
} finally {
pm.close();
}
return e;
}
public void updateEmployeeTitle(Employee e, String newTitle) {
if (titleChangeIsAuthorized(e, newTitle) {
e.setTitle(newTitle);
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
pm.makePersistent(e);
} finally {
pm.close();
}
} else {
throw new UnauthorizedTitleChangeException(e, newTitle);
}
}
Objetos desanexados são uma ótima alternativa para criar objetos de transferência de dados. Para obter mais informações sobre como trabalhar com objetos desanexados, consulte a documentação do DataNucleus.
Para excluir um objeto do armazenamento de dados, chame o método deletePersistent() do PersistenceManager com o objeto:
pm.deletePersistent(e);
Se um objeto tiver campos que contêm objetos filho que também são persistentes, os objetos filho também serão excluídos. Consulte Relacionamentos para obter mais informações.