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á!