sábado, 21 de março de 2009

Tagged under: , , ,

Persistência orientada a objetos com db4o (parte 2)

Continuando o post anterior, vamos agora ver mais funcionalidades do db4o.

Para recuperar os objetos, o db4o implementou três sistemas diferentes de consulta: Query By Example (QBE), Native Queries (NQ), e a SODA Query API (SODA). Vamos começar com a QBE pois é mais simples de entender.

Quando usar a QBE para recuperar os objetos no db4o, você deve criar um "protótipo" de seu objeto para usar como exemplo do que deve ser recuperado. A instância de ObjectContainer recuperará os objetos que se pareçam com o protótipo informado.

Crie uma classe chamada Passo2.java conforme o código abaixo:


package javabahia.app;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import javabahia.entidade.Contrato;

/**
* Segundo passo de execução do teste com o db4o.
* @author Alexandre
*/

public class Passo2 {

public static void main(String[] args) {
// abrindo o arquivo db4o
ObjectContainer db = Db4o.openFile("javabahia.dbo");

try {
// criando o prototipo de exemplo
Contrato proto = new Contrato(1000, null, null, null, null);

// invocando a consulta QBE
ObjectSet<Contrato> result = db.queryByExample(proto);

// listando os objetos encontrados
System.out.println(result.size() + " objetos foram encontrados.");
for (Contrato ctr : result) {
System.out.println("Contrato número " + ctr.getNumero());
}

} finally {
// fechando o arquivo db4o
db.close();
}
}
}


No código acima, recuperamos todos os objetos da classe Contrato que possuem número igual a 1000. Como só inserimos um objeto no último post deste blog, o resultado esperado ao executar essa classe deve ser:

1 objetos foram encontrados.
Contrato número 1000


Atualizar os objetos no db4o é tão fácil quanto inseri-los; basta chamar store() novamente. Crie uma classe chamada Passo3.java conforme o código abaixo para observar isso.


package javabahia.app;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import javabahia.entidade.Contrato;
import javabahia.entidade.Empresa;

/**
* Terceiro passo de execução do teste com o db4o.
* @author Alexandre
*/

public class Passo3 {

public static void main(String[] args) {
// abrindo o arquivo db4o
ObjectContainer db = Db4o.openFile("javabahia.dbo");

try {
// criando o prototipo de exemplo para recuperar a empresa
Empresa protoEmp = new Empresa("11000111000100", null, null);

// recuperando a empresa
ObjectSet<Empresa> empresas = db.queryByExample(protoEmp);
Empresa emp = empresas.next();

// atualizando os dados da empresa
emp.setNome("ACME S/A");
emp.setEmail("faleconosco@acme.com.br");

// armazenando a empresa
db.store(emp);

// invocando a consulta QBE para recuperar todos os contratos
ObjectSet<Contrato> contratos = db.queryByExample(Contrato.class);

// listando os objetos encontrados
System.out.println(contratos.size() + " objetos foram encontrados.");
for (Contrato ctr : contratos) {
System.out.println("Contrato número " + ctr.getNumero() + ", com a empresa " + ctr.getContratada().getEmpresa().getNome());
}

} finally {
// fechando o arquivo db4o
db.close();
}
}
}


No código acima, criamos um protótipo para recuperar a empresa e depois atualizamos os dados dela (nome e e-mail) no banco de dados db4o. Em seguida, recuperamos todos os contratos de uma forma diferente - bastando passar a classe de exemplo. É outra maneira de usar a QBE no db4o. O resultado esperado deve ser esse:

1 objetos foram encontrados.
Contrato número 1000, com a empresa ACME S/A


Por fim, para excluir um objeto do db4o invocamos o método delete() da instância do ObjectContainer. Crie uma classe chamada Passo4.java conforme o código abaixo:


package javabahia.app;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import javabahia.entidade.Usuario;

/**
* Quarto passo de execução do teste com o db4o.
* @author Alexandre
*/

public class Passo4 {

public static void main(String[] args) {
// abrindo o arquivo db4o
ObjectContainer db = Db4o.openFile("javabahia.dbo");

try {
// invocando a consulta QBE para recuperar todos os usuários
ObjectSet<Usuario> usuarios = db.queryByExample(Usuario.class);

// deletando todos os usuários
for (Usuario usu : usuarios) {
db.delete(usu);
}

} finally {
// fechando o arquivo db4o
db.close();
}
}
}


Nós criamos, recuperamos, atualizamos e excluimos objetos com apenas algumas linhas de código. Como podemos perceber, usar o db4o é muito mais natural para a desenvolvimento orientado a objetos do que ficar criando consultas SQL e usando a API JDBC para suportar um banco de dados relacional.

Porém, o que fizemos até agora é o trivial mais básico que pode existir nesse framework. O db4o é mais poderoso do que isso que foi mostrado. Em outros posts futuros mostrarei como fazer atualização e exclusão em cascata, como usar os outros métodos de consulta e como usar o db4o remotamente. Até lá!

sexta-feira, 20 de março de 2009

Tagged under: , , ,

Persistência orientada a objetos com db4o

O db4o é um framework de persistência que armazena os objetos exatamente como eles são representados em bytecode na plataforma Java ou em CIL na plataforma .NET. O objetivo desse framework é tornar a vida do desenvolvedor mais fácil ao dar-lhe uma opção de usar uma persistência mais próxima do seu ambiente puramente orientado a objetos.

O db4o possui a mesma confiabilidade encontrada em bancos de dados relacionais por suportar transações ACID. Se uma falha ocorre, os objetos são restaurados para o primeiro estado consistente antes de a transação iniciar. O controle de concorrência e lock é também semelhante ao dos bancos de dados relacionais.

O engine do db4o é simplesmente um JAR (db4o-x.x-javaX.jar) ou uma DLL (Db4oFactory.Db4o.dll), dependendo do ambiente escolhido, e é somente deles que precisamos para utilizar o framework. Como estamos num grupo de usuários que lida com a plataforma Java, você pode obter a última versão para a plataforma Java em http://www.db4o.com/DownloadNow.aspx. A versão que usaremos aqui nesse post é a 7.4.

Ao descompactar o arquivo baixado do site, copie o arquivo db4o-7.4-java5.jar (versão para Java 5 ou superior, que suporta Generics, AutoBoxing e as novidades adicionadas recentemente à linguagem) para uma pasta isolada. Crie uma entrada na sua IDE preferida para esse arquivo. Por exemplo, eu usarei o Netbeans nesse post e isso seria equivalente a criar uma biblioteca na IDE e adicionar esse arquivo JAR a ela.

Crie um projeto na sua IDE e adicione a entrada para o arquivo JAR ao projeto recém-criado. Como eu estou usando o Netbeans, criei um projeto Java Class Library chamado JavaBahia4O e adicionei a biblioteca db4o ao projeto.

Para entendermos como funciona esse framework, vamos utilizar o mesmo contexto de domínio modelado para o tutorial "Desenvolvendo uma aplicação web de forma fácil e prática".


Relembrando, pelo diagrama de classes acima, todo objeto da classe Contrato possui um Usuário cadastrante e uma Empresa contratada. A partir da relação entre um Contrato e uma Empresa, nasce a classe Contratada, que possui informações bancárias para pagamento daquele contrato; outro contrato com a mesma empresa poderá ser pago em uma conta bancária diferente.

Vamos criar as classes Usuario, Empresa, Contrato e Contratada e colocá-las no pacote javabahia.entidade.


Usuario.java:


package javabahia.entidade;

/**
* Classe da entidade Usuário.
* @author Alexandre
*/

public class Usuario {

private String login;
private String senha;
private String nome;
private String email;

public Usuario(String login, String senha, String nome, String email) {
this.login = login;
this.senha = senha;
this.nome = nome;
this.email = email;
}

// get's e set's omitidos
}


Empresa.java:


package javabahia.entidade;

/**
* Classe da entidade Empresa.
* @author Alexandre
*/

public class Empresa {

private String cnpj;
private String nome;
private String email;

public Empresa(String cnpj, String nome, String email) {
this.cnpj = cnpj;
this.nome = nome;
this.email = email;
}

// get's e set's omitidos
}


Contrato.java:


package javabahia.entidade;

import java.util.Date;

/**
* Classe da entidade Contrato.
* @author Alexandre
*/

public class Contrato {

private Contratada contratada;
private Integer numero;
private String objeto;
private Date dataAssinatura;
private Integer prazoVigencia;
private Usuario cadastrante;

public Contrato(Integer numero, String objeto, Date dataAssinatura, Integer prazoVigencia, Usuario cadastrante) {
this.numero = numero;
this.objeto = objeto;
this.dataAssinatura = dataAssinatura;
this.prazoVigencia = prazoVigencia;
this.cadastrante = cadastrante;
}

// get's e set's omitidos
}


Contratada.java:


package javabahia.entidade;

/**
* Entidade da classe Contratada.
* @author Alexandre
*/

public class Contratada {

private Contrato contrato;
private Empresa empresa;
private Integer codigoBanco;
private String agenciaBanco;
private String contaBanco;

public Contratada(Contrato contrato, Empresa empresa, Integer codigoBanco, String agenciaBanco, String contaBanco) {
this.contrato = contrato;
this.empresa = empresa;
this.codigoBanco = codigoBanco;
this.agenciaBanco = agenciaBanco;
this.contaBanco = contaBanco;
}

// get's e set's omitidos
}


Note que as classes das entidades não contém qualquer código intrusivo do framework.

Para acessar o arquivo do banco de dados db4o, invocamos o método Db4o.openFile() passando como parâmetro o caminho para o arquivo. Isso retornará uma instância de ObjectContainer, que representa o seu banco de dados db4o e será sua principal interface de acesso a ele. Se o arquivo não existir, ele será criado automaticamente. O método close() fecha o arquivo e libera qualquer recurso preso a ele.

Para armazenar um objeto no banco de dados, invocaremos o método store() da instância de ObjectContainer, passando como parâmetro o objeto a ser persistido. Simples assim!

Para visualizar o que foi dito, crie uma classe chamada Passo1.java com o seguinte código:


package javabahia.app;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import java.util.Date;
import javabahia.entidade.Contratada;
import javabahia.entidade.Contrato;
import javabahia.entidade.Empresa;
import javabahia.entidade.Usuario;

/**
* Primeiro passo de execução do teste com o db4o.
* @author Alexandre
*/

public class Passo1 {

public static void main(String[] args) {
// abrindo o arquivo db4o
ObjectContainer db = Db4o.openFile("javabahia.dbo");

try {
// criando um usuário
Usuario usu = new Usuario("teste", "1234", "Usuário de Teste", "teste@teste.br");
// armazenando o usuário acima
db.store(usu);

// criando uma empresa
Empresa emp = new Empresa("11000111000100", "ACME Ltda", "acme@acme.com");
// armazenando a empresa acima
db.store(emp);

// criando o contrato
Contrato ctr = new Contrato(1000, "Compra de roupas", new Date(), 30, usu);
// criando a relação com a empresa contratada
Contratada ctda = new Contratada(ctr, emp, 123, "1234-5", "12345-X");
ctr.setContratada(ctda);

// armazenando o contrato e a sua contratada respectivamente
db.store(ctr);

} finally {
// fechando o arquivo db4o
db.close();
}
}
}


No código acima, armazenamos instâncias de Usuario e Empresa isoladamente. Em seguida armazenamos instâncias de Contrato e Contratada com apenas uma chamada ao método store() passando apenas o contrato. O db4o possui capacidade de entender quais objetos associados ao objeto que se pede para persistir já existem no banco de dados ou são novos. Assim, nesse exemplo, o db4o, ao persistir o contrato, persistiria também a contratada, pegando apenas a referência ao usuário e empresa já cadastrados.

Por hoje, vou ficando por aqui. No próximo post eu mostrarei como recuperar os objetos, atualizá-los e excluí-los. Ate lá!