Documente Academic
Documente Profesional
Documente Cultură
Castor JDO
Persistência Fácil de Objetos em Java
HERVAL FREIRE DE A. JÚNIOR
As camadas de persistência facilitam o desenvolvimento de aplicações com acesso
a banco de dados. Aprenda a usar a API Castor através de um exemplo simples.
Nota: Apesar do nome, o pacote JDO do Castor não implementa a especificação JDO da Sun em
sua totalidade. É importante lembrar que muitos recursos, especialmente no que diz respeito à
linguagem de consulta OQL, ainda estão em desenvolvimento no projeto.
Funcionario
+gerent e
cod igo : int
nome : Stri ng Set or
foto : byte [] 0..* 0..* codigo : int
salario : double nome : String
gratificacao : double telefone : String
nascimento : Da te +operario
tele fone : String
0..* 0..1
O primeiro passo para que possamos trabalhar com a persistência das classes no banco de dados é
criar um esquema físico de armazenamento. Para que a persistência seja possível, o esquema
mostrado na figura 2 foi criado no banco de dados. Para os testes, foi utilizada uma base de dados
MySQL – um dos SGBDs suportados pelo Castor.
tb_func tb_setor
PK codigo PK codigo
foto nome
nasc fone
name
salario
FK1 setor
fone
gratificacao
tb_gerente_setor
PK,FK1 cod_gerente
PK,FK2 cod_setor
class Setor {
private String nome;
private String telefone;
private Computador computadores;
3
class Funcionario {
Modelagem do BD
O script da listagem 2 gera a as tabelas necessárias para os testes.
Uma vez que temos toda esta estrutura disponível, podemos partir para o primeiro passo do
processo de configuração do ambiente Castor.
db = jdo.getDatabase();
Neste código, informamos ao objeto JDO que as configurações de dados encontram-se no arquivo
“database.xml”. Ao executar o método getDatabase(), o objeto JDO procurará a configuração
relativa ao banco de dados de nome “empresa_db”. Após recuperar o objeto Database, o
programador precisa iniciar uma transação para que possa trabalhar os objetos e então executar
quaisquer operações livremente. A persistência dos dados somente é realizada na chamada ao
método commit(). Caso seja necessário, existe também um método “rollback()” na classe Database,
o que permite que a transação seja desfeita em caso de problemas no fluxo de execução.
InitialContext ctx;
UserTransaction ut;
Database db;
db.close();
Como na maioria dos casos a transação é gerenciada pelo container, o programador não precisa especificar
seu início e fim explicitamente. Alguns containers open-source vem utilizando o Castor desta forma, como
framework de persistência de EJBs.
No nosso exemplo específico, para que o banco de dados possa ser aberto e utilizado, o descritor
database.xml tem o conteúdo mostrado na listagem 4:
Listagem 4. Arquivo database.xml
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version 1.0//EN" "jdo-conf.dtd">
<database name="empresa_db" engine="mysql">
<driver class-name="org.gjt.mm.mysql.Driver" url="jdbc:mysql://localhost/empresaBD">
<param name="user" value="herval" />
<param name="password" value="herval" />
</driver>
<mapping href="tabelas.xml" />
</database>
determina a existência ou não de alguns recursos, como veremos no decorrer do tutorial. O atributo “engine”
pode receber, atualmente, os valores mostrados na tabela 1, a seguir
<class>
…
</class>
</mapping>
O elemento <class> tem sua estrutura mostrada na listagem 6. Para descrever e especificar cada
atributo da classe específica, o elemento <class> comporta um número arbitrário de elementos
<field>, um para cada atributo mapeado para um campo na tabela.
get-method – determina o nome do método getter do atributo, caso a assinatura não siga o padrão
da especificação JavaBean (public <tipo> get<Atributo>())
set-method - determina o nome do método setter do atributo, caso a assinatura não siga o padrão
da especificação JavaBean (public void set<Atributo>(<tipo> valor))
collection – determina o tipo, no caso de um atributo que seja uma coleção. As coleções possíveis
são arrays, Vectors, Hashtables, ArrayLists, HashSets e HashMaps do tipo definido pelo atributo
“type”. O valor recebido por este atributo para cada caso é, respectivamente, “array”, “vector”,
“hashtable”, “collection”, “set” e “map”.
Dos elementos internos da tag <field>, apenas o elemento <sql> é interessante para nosso estudo
atual. A sua estrutura é mostrada na listagem 8.
Listagem 8. DTD do elemento XML <sql>
<!ELEMENT sql EMPTY>
<!ATTLIST sql
name NMTOKEN #REQUIRED
type NMTOKEN #IMPLIED
many-key NMTOKEN #IMPLIED
many-table NMTOKEN #IMPLIED
read-only ( true | false ) "false"
dirty ( check | ignore ) “check” >
Datas também podem ser mascaradas para armazenamento no banco de dados, em casos onde o
formato de armazenamento do banco seja diferente do formato fornecido pelo método toString() da
classe Date. O exemplo da listagem 10 ilustra um exemplo de formatação para armazenar datas no
formato “dd/mm/yyyy”
many-key – atributo utilizado para relacionamentos 1-para-n ou n-para-n: indica o nome da chave
estrangeira que identifica unicamente objetos do tipo dado por “type” que se relacionam com a
classe que contém esta definição.
many-table – nome da tabela intermediária, no caso de relacionamentos n-para-n normalizados
que utilizam uma tabela para relacionar os objetos.
Podemos identificar, neste nosso caso, exemplos de aplicação de formatadores para data (atributo
“nascimento”), um relacionamento um-para-muitos (atributo “setor”), um relacionamento muitos-
para-muitos (atributos “setoresGrenciados”) e diversos outros atributos mapeados para tipos
diversos no banco de dados SQL. Dentre os atributos mapeados, o mais incomum é o nosso
relacionamento n-para-n com a classe Setor (atributo “setoresGerenciados”): este especifica o
atributo “many-table” com o nome da tabela que relaciona gerentes a setores e o atributo “name” da
tag <sql> como o campo chave que identifica setores na tabela “tb_gerente_setor”.
O mapeamento da classe Setor é ainda mais simples e pode ser visto na listagem 12.
Listagem 12. Mapeamento da classe Setor
<class name="example.Setor" identity="codigo" key-generator="IDENTITY">
<map-to table="tb_setor" />
Após escrever estes mapeamentos, podemos finalmente começar a trabalhar com as classes em
Java normalmente, sem preocupações maiores com utilização de SQL para persistência e
10
recuperação de objetos. Graças à camada de persistência, todo o código de acesso ao banco que
precise ser gerado será criado e executado automaticamente, como veremos nos exemplos a seguir.
Conclusões
A utilização de uma camada de persistência para interação com o banco de dados trás uma série
de vantagens, especialmente visíveis no desenvolvimento de aplicações de maior porte.
A remoção de acessos a banco de dados utilizando SQL inserido no meio do código da aplicação,
a facilidade de modificação dos mapeamentos em tempo de deployment e a possibilidade de
configurar detalhes de armazenamento dos dados em um arquivo de configuração são apenas alguns
exemplos dos benefícios apresentados pelo Castor e em outras APIs de persistência de objetos. Sem
dúvida, a adoção de camadas de persistência como um elemento arquitetural durante o
desenvolvimento de aplicações garante produtividade, qualidade e confiabilidade de código.
Referências
http://www.exolab.org – site oficial do projeto Castor
http://Jakarta.apache.org/ojb – site do projeto OJB, uma camada de persistência compatível com a
especificação ODMG
http://www.AmbySoft.com/ - artigos sobre construção de camadas de persistência de objetos
http://hibernate.sourceforge.net - API Hibernate de persistência para bancos de dados relacionais