DB4Objects – Parte II – Mãos a Obra
Mãos à obra
Para começarmos o nosso exemplo hands on, será necessário fazer o download da última versão do db4o. Atualmente está na versão 5.5 e pode ser baixado em http://developer.db4o.com/files/default.aspx. O ObjectManager também será parte do tutorial (que vem a seguir) podendo ser baixado no mesmo link. A IDE utilizada nos exemplos será o Eclipse, com o JDK 5.0.
Analisando o conteúdo do arquivo disponibilizado na versão 5.5
Visão Geral da API
Pacote com.db4o
Agrupa as principais classes/interfaces utilizadas para manipular o banco. A classe Db4o é a factory class que fornece métodos estáticos permitindo abrir e conectar um arquivo de banco de dados. A Interface ObjectContainer fornece os métodos para armazenar, consultar, deletar, e efetuar transações (commit e rollback transctions).
Pacote com.db4o.ext
Contém algumas funcionalidades a mais que o pacote com.db4o. Essa separação foi feita para ocultar a complexidade das classes/interfaces do pacote, para que sejam enfatizados os principais métodos de manipulação do db4o.
Pacote com.db4o.config
Contém as classes necessárias para configurar o db4o.
Pacote com.db4o.query
Contém as classes necessárias para a criação das querys S.O.D.A e Querys nativas.
Configurando o Projeto
Crie um novo projeto no Eclipse e adicione ao CLASSPATH de sua aplicação o arquivo db4o-5.5-java5.jar. Este é o único arquivo necessário para que a nossa aplicação “converse” com o banco. Para não perder o foco, vale ressaltar que a preocupação aqui não é com a arquitetura, ou camadas e padrões.
Iniciando o projeto
Primeiramente vamos criar o nosso bean, que será armazenado no banco de dados:
package br.com.javamagazine;
public class Cliente {
private int codigo;
private String nome;
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String toString(){
return "Codigo: "+ codigo + " Nome: " + nome;
}
}
O mais interessante é que não precisamos implementar nenhuma interface ou extender alguma classe relacionada ao db4o, eliminando qualquer tipo de dependência.
Abrindo o banco de dados
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
public class {
public static void main(String[] args) {
ObjectContainer db = Db4o.openFile("c:/guerra.yap");
try {
// algum código db4o
} finally {
db.close();
}
}
}
A classe Db4o possui o método estático openFile(String caminhoBanco) que retorna um ObjectContainer, que será utilizado para as operações de CRUD.
Inserindo Objetos
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
public class Main {
public static void main(String[] args) {
ObjectContainer db = Db4o.openFile("c:/guerra.yap");
try {
Cliente cli = new Cliente(2, "Glaucio");
db.set(cli);
System.out.println("Cliente armazenado: " + cli);
} finally {
db.close();
}
}
}
Saída:
Cliente armazenado: Código: 2 Nome: Glaucio
No código acima, foi instanciado um objeto cliente, alimentando as propriedades através do construtor (O db4o também aceita objetos sem construtor). Para armazenar o cliente no banco é necessário passar como parâmetro a instancia de cliente para o método set() da classe ObjectContainer. Em uma linha de comando já efetuamos a operação de inserção.
Recuperando Objetos
Existem três formas para recuperar objetos no banco: através da QBE (Query By Example), NQ (Native Queries) e S.O.D.A (SODA Query API. Vamos ver como funciona o QBE:
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
public class Main {
public static void main(String[] args) {
ObjectContainer db=Db4o.openFile("c:/guerra.yap");
Cliente cliente = new Cliente(0,"Glaucio");
//Recuperar todos os clientes com nome Glaucio
ObjectSet<Cliente> lista = db.get(cliente);
while (lista.hasNext()){
System.out.println(lista.next());
}
}
}
Saída:
Codigo: 2 Nome: Glaucio
Codigo: 1 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
[db4o 5.5.1 2006-12-07 10:07:28]
'c:/guerra.yap' closed by ShutdownHook.
Utilizamos o zero para não especificar o código do cliente, já que zero é o valor padrão para inteiros. Selecionamos todos os clientes de nome Glaucio, independente do código.
Selecionando todos os objetos Cliente:
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
public class Main {
public static void main(String[] args) {
ObjectContainer db=Db4o.openFile("c:/guerra.yap");
//Recuperar todos os clientes
ObjectSet<Cliente> lista = db.get(Cliente.class);
while (lista.hasNext()){
System.out.println(lista.next());
}
}
}
Saída:
Codigo: 452 Nome: Guerra
Codigo: 2 Nome: Glaucio
Codigo: 1 Nome: Glaucio
Codigo: 777 Nome: Luiz
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
[db4o 5.5.1 2006-12-07 10:19:16]
'c:/guerra.yap' closed by ShutdownHook.
Mais a frente estaremos vendo com mais detelhes as outras formas de consulta no db4o.
Atualizando objetos
Atualizar objetos é tão simples quanto recuperá-los. Veja o exemplo abaixo:
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
public class Main {
public static void main(String[] args) {
ObjectContainer db=Db4o.openFile("c:/guerra.yap");
//Seleciona o cliente Maria de codigo 777
ObjectSet<Cliente> lista = db.get(new Cliente (777,"Maria"));
//Recupera o cliente
Cliente cliente = lista.next();
//Atualiza o nome no objeto
cliente.setNome("Maria José");
//Atualiza o banco
db.set(cliente);
//Lista o resultado alterado
lista = db.get(Cliente.class);
while (lista.hasNext()){
System.out.println(lista.next());
}
}
}
Saída:
Codigo: 452 Nome: Guerra
Codigo: 2 Nome: Glaucio
Codigo: 1 Nome: Glaucio
Codigo: 777 Nome: Maria José
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
[db4o 5.5.1 2006-12-07 10:41:07]
'c:/guerra.yap' closed by ShutdownHook.
Lembre-se de sempre utilizar o método set(Objeto) para atualizar o objeto no banco. Automaticamente o db4o identifica se o objeto foi retirado do banco para atualização,caso contrário ele armazenará um novo objeto.
Excluindo Objetos
O processo de exclusão é semelhante ao de atualização. Primeiro retiramos o objeto do banco, depois utilizamos a função delete da classe ObjectContainer:
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
public class Main {
public static void main(String[] args) {
ObjectContainer db=Db4o.openFile("c:/guerra.yap");
//Seleciona o cliente Maria de codigo 777
ObjectSet<Cliente> lista = db.get(new Cliente (777,"Maria José"));
//Recupera o cliente
Cliente cliente = lista.next();
//Deleta o objeto
db.delete(cliente);
//Lista o resultado alterado
lista = db.get(Cliente.class);
while (lista.hasNext()){
System.out.println(lista.next());
}
}
}
Saída:
Codigo: 452 Nome: Guerra
Codigo: 2 Nome: Glaucio
Codigo: 1 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
[db4o 5.5.1 2006-12-07 10:58:47]
'c:/guerra.yap' closed by ShutdownHook.
Um pouco mais sobre SODA Queries
Vamos imaginar o cenário em que precisamos selecionar todos os clientes com código menor que 2.
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Query;
public class Main {
public static void main(String[] args) {
ObjectContainer db=Db4o.openFile("c:/guerra.yap");
Query query = db.query();
query.constrain(Cliente.class);
query.descend("codigo").constrain(2).smaller();
//Lista o resultado alterado
ObjectSet<Cliente> lista = query.execute();
while (lista.hasNext()){
System.out.println(lista.next());
}
}
}
Vamos analisar o código passo a passo:
1) O código acima instancia uma classe do tipo query, que seleciona os objetos do tipo Cliente.
2) O método descend seleciona a propriedade do objeto que será analisada.
3) Adicionamos o valor do código através do método constrain().
4) O método smaller() completa a query dizendo que selecionaremos os códigos menores que dois.
Para quem está familiarizado com o Hibernate, já vê muitas semelhanças nas operações de CRUD e de query.
Querys avançadas
Selecionar todos os clientes que não tenham o nome “Glaucio”:
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Query;
public class Main {
public static void main(String[] args) {
ObjectContainer db=Db4o.openFile("c:/guerra.yap");
Query query = db.query();
query.constrain(Cliente.class);
query.descend("nome").constrain("Glaucio").not();
//Lista o resultado alterado
ObjectSet<Cliente> lista = query.execute();
while (lista.hasNext()){
System.out.println(lista.next());
}
}
}
Saída:
Codigo: 452 Nome: Guerra
[db4o 5.5.1 2006-12-07 11:36:58]
'c:/guerra.yap' closed by ShutdownHook.
Recuperar todos os clientes com nome Glaucio E código igual a dois.
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Constraint;
import com.db4o.query.Query;
public class Main {
public static void main(String[] args) {
ObjectContainer db=Db4o.openFile("c:/guerra.yap");
Query query = db.query();
query.constrain(Cliente.class);
Constraint constrain = query.descend("nome").constrain("Glaucio");
query.descend("codigo").constrain(2).and(constrain);
//Lista o resultado alterado
ObjectSet<Cliente> lista = query.execute();
while (lista.hasNext()){
System.out.println(lista.next());
}
}
}
Listar todos os clientes em ordem crescente:
package br.com.javamagazine;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Constraint;
import com.db4o.query.Query;
public class Main {
public static void main(String[] args) {
ObjectContainer db=Db4o.openFile("c:/guerra.yap");
Query query = db.query();
query.constrain(Cliente.class);
query.descend("codigo").orderAscending();
//Lista o resultado alterado
ObjectSet<Cliente> lista = query.execute();
while (lista.hasNext()){
System.out.println(lista.next());
}
}
}
Saída:
Codigo: 1 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 2 Nome: Glaucio
Codigo: 452 Nome: Guerra
[db4o 5.5.1 2006-12-07 12:15:14]
'c:/guerra.yap' closed by ShutdownHook.
Para ordem decrescente utilize o método o orderDescending().