• Nenhum resultado encontrado

CLASSES DE OBJETOS PERSISTENTES

No documento EMULADOR DE SGBD ORIENTADO A OBJETOS (páginas 98-101)

Os objetos persistentes precisam de duas classes Java para funcionar: uma interface que é independente do SGBDR usado (em geral, o ambiente Java considera que uma interface é uma classe), e uma classe específica para o SGBDR usado, que implementa a interface.

A interface independente de SGBDR define os seguintes métodos: a) save();

b) destroy();

c) métodos que operam em coleções globais;

d) métodos que acessam os atributos e relacionamentos da classe (getters e setters). A classe dependente do SGBDR implementa estes métodos, e adiciona o seguinte: a) variáveis para guardar o valor dos atributos e dos relacionamentos;

b) uma variável para guardar o OID (do tipo long);

c) uma variável para guardar o contexto (do tipo referência para IObjectContext); d) variáveis de controle, que guardam informações a respeito do estado dos atributos. 5.5.1 Estados dos atributos

Para beneficiar a performance, o valor dos atributos e relacionamentos não são carregados imediatamente quando o objeto é lido, pois não há garantia de que eles serão usados. Da mesma forma, quando o objeto é salvo, somente os valores alterados são colocados no comando UPDATE que vai ao SGBDR. Isto implica que um atributo qualquer de um objeto persistente tem os seguintes estados:

a) não-lido, na qual o valor do atributo é desconhecido e depende de um acesso ao SGBDR;

b) lido, na qual o valor do atributo é conhecido e não foi alterado;

c) sujo, na qual o valor foi alterado pelo programador e fará parte do comando UPDATE quando o objeto for salvo.

Estes estados não são usados antes de o objeto ser persistido pela primeira vez, pois esta operação implica num comando INSERT envolvendo todos os atributos. Após a inserção, todos os atributos possuem o estado "lido".

Quando é feita uma consulta, a maioria dos atributos ficam no estado "não-lido", sendo que alguns ficam no estado "lido", pois seu valor pode ser descoberto durante a consulta. A mudança de "não-lido" para "lido" ocorre quando o getter do atributo é chamado. Nesta ocasião, o valor do atributo é lido do SGBDR, e isto pode implicar num impacto à performance. Trata-se de uma limitação bem conhecida do software.

A mudança para "sujo" ocorre quando o setter do atributo é chamado. Nesta ocasião, o valor do atributo e o estado anteriores do atributo são ignorados. A mudança de "sujo" para "lido" ocorre quando o objeto é salvo.

Quando o save() é chamado num objeto que não possui atributos sujos, não ocorre qualquer acesso ao SGBDR, e a chamada é simplesmente ignorada.

5.5.2 Primeira chamada ao save()

Quando um objeto é instanciado através do método newInstance(Class), de IObjectContext, o valor da variável que mantém seu OID é zero. Quando o método save() é chamado para um objeto cujo OID é zero, trata-se da primeira chamada ao save().

A primeira coisa que ela faz é solicitar ao contexto um OID (a operação de computar o OID será descrita mais adiante). Depois é aberta uma transação local, e é inserido um registro em cada tabela definida no mapeamento para guardar uma parte do estado do objeto. Cada registro recebe o OID do objeto e o valor dos atributos correspondentes. Também são setados os campos das coleções globais. Se tudo transcorreu sem problemas, a transação é confirmada e o método retorna. Nestas circunstâncias, o estado de todos os atributos será "lido", e o valor da variável que guarda o OID será o valor do OID.

Se houve algum problema, são tomadas as medidas para que o método save() não apresente efeitos colaterais. A transação é abortada, e o valor da variável OID permanecerá zero. A exceção que informa a causa o problema será propagada para o chamador. A maioria dos problemas que ocorrem no método save() são causados por tentativas de violar invariantes (como tentar inserir mais de um objeto com a mesma chave, ou deixar nulo um atributo que é obrigatório). Assim sendo, o chamador poderá corrigir o problema na mesma instância, e depois invocar o método save() novamente.

5.5.3 Chamadas ao save() para um objeto já persistido

Quando o método save() é chamado para um objeto cujo OID é diferente de zero, trata-se de uma chamada para um objeto já persistido.

Inicialmente o método monta comandos UPDATE, com base nos atributos que estão no estado "sujo". É montado um comando UPDATE para cada tabela definida no mapeamento para guardar uma parte do estado do objeto. Estes comandos UPDATE sempre contém a cláusula where OID=valor-do-OID, e sem qualquer filtro adicional. Depois é aberta uma transação e cada comando UPDATE é emitido ao SGBDR. Se tudo transcorreu sem problemas, a transação é confirmada e o método retorna. Nestas circunstâncias, todos os atributos que tinham o estado "sujo" passarão a ter o estado "lido".

Se houve algum problema, são tomadas as medidas para que o método save() não apresente efeitos colaterais. A transação é abortada. A exceção que informa a causa o problema será propagada para o chamador. A maioria dos problemas que ocorrem no método save() são causados por tentativas de violar invariantes (como tentar inserir mais de um objeto com a mesma chave, ou deixar nulo um atributo que é obrigatório). Assim sendo, o chamador poderá corrigir o problema na mesma instância, e depois invocar o método save() novamente.

5.5.4 O método destroy()

O método destroy() faz com que um objeto seja destruído na base persistente. A primeira coisa que ele faz é montar um comando DELETE para cada tabela definida no mapeamento para guardar uma parte do estado do objeto. Estes comandos DELETE sempre contém a cláusula where OID=valor-do-OID, e sem qualquer filtro adicional. Depois são montados comandos UPDATE para limpar referências fracas e suaves. Finalmente é aberta uma transação e os comandos são submetidos ao SGBDR. Se tudo transcorreu sem problemas, a transação é confirmada, atribui-se zero para a variável que guarda o OID, e o método retorna.

Se houve algum problema, em geral é porque existem referências fortes para o objeto sendo destruído. A transação é abortada, e o método retorna sem qualquer mudança em suas variáveis.

5.5.5 Métodos que operam em coleções globais

Cada coleção global onde pode estar um objeto implica na existência de dois métodos na interface e portanto, na implementação:

a) o método addToColeção(), que adiciona o objeto na coleção correspondente; b) o método removeFromColeção(), que remove o objeto de tal coleção.

Como a coleção global mapeia para um simples campo lógico no SGBDR, o método addToColeção() apenas realiza um UPDATE setando aquele campo para true. O método removeFromColeção() faz a mesma coisa, mas seta o campo para false. Chamadas a estes métodos sempre implicam no salvamento do objeto.

No documento EMULADOR DE SGBD ORIENTADO A OBJETOS (páginas 98-101)

Documentos relacionados