[ TUTORIAL ] Android – Banco de dados db4o exemplo de como utilizar

Este post possui como tema principal a persistência na plataforma Android através de uma base de dados totalmente orientada a objetos chamada db4o.
Não tratarei aqui assuntos como design patterns, nomenclaturas e etc… Basicamente um “Hello World” no android com db4o.

ATENÇÃO ESTE BANCO FOI DESCONTINUADO! NÃO UTILIZEM! Conforme anunciado aqui: http://supportservices.actian.com/versant/default.html

Existem vários tutorias na internet sobre como utilizar o db4o, mas como a maioria deles são em inglês resolvi fazer um tutorialzinho em português para a galera que não manja muito de inglês e tem dificuldade com isso, e claro quanto mais a galera contribuir mais a comunidade brasileira se fortalece =)

  • Porque utilizar bases OO?

    • Agilizam o desenvolvimento de aplicações, pois não são necessárias conversões do modelo OO para o modelo relacional.
    • Fácil manutenção.

    Obs.: Não posso falar sobre desempenho, afinal não realizei meus teste comparando o SQLite com o db4o.

  • Como utilizar?

    Neste exemplo vamos criar um projeto simples só para demostrar algumas funções básicas, salvando uma String na base, listando todas as Strings e deletando todas.
    Então vamos lá!

    Crie um novo projeto Android no Eclipse.  Ele te fornece a opção de criar o “Hello World” criando assim uma  Activity (MainActivity) e o arquivo XML responsável pelo Layout (activity_main), assumirei que você selecionou essa opção.

    Com o arquivo que baixamos anteriormente em mãos (cerca de 40 MB), descompacte o mesmo em um local de sua preferência, em seguida acesse a pasta e copie o arquivo db4o-X.XX-core-java5 como pode ser visualizado na figura a seguir.

    db4o coreCole o arquivo na pasta libs do projeto, assim você estará adicionando o db4o ao seu projeto.

    OBS.: Dependendo da versão do plugin do eclipse que você está utilizando será necessário ir até as propriedades do projeto e adicionar esse .jar no build path do projeto, caso isso não de certo as classes que vamos criar a seguir irão apresentar erros.

    Crie uma classe chamada “Palavra”, com um campo String e seus respectivos get/set. Essa classe será responsável por manter os dados, sua classe deve ficar semelhante a isso:

    [sourcecode language="java"]
    public class Palavra {

    private String texto;

    public String getTexto() {
    return texto;
    }

    public void setTexto(String texto) {
    this.texto = texto;
    }
    }

    [/sourcecode]

    Para deixar bem claro as duas classes a seguir eu retirei deste post.
    Crie uma classe chama Db4oHelper, que terá como sua responsabilidade criar, configurar a base de dados do db4o e fornecer o ObjectContainer para os Providers realizarem ações como salvar, deletar e etc.. leia os poucos comentários da classe e caso houver alguma dúvida poste nos comentários.
    Como já comentei anteriormente, não tratarei de design patterns, ou seja se for utilizar o db4o para algo mais complexo sugiro que leia sobre padrões de projeto.

    [sourcecode language="java"]

    import android.content.Context;
    import android.util.Log;

    import com.db4o.Db4oEmbedded;
    import com.db4o.ObjectContainer;
    import com.db4o.config.EmbeddedConfiguration;

    public class Db4oHelper {
    private ObjectContainer database = null;

    private String DATABASE_NAME = "pedreiros_do_software.db4o";

    public Db4oHelper(Context context) {
    try {
    if (database == null || database.ext().isClosed()) {
    database = Db4oEmbedded.openFile(config(),
    db4oDBFullPath(context));
    }
    } catch (Exception ie) {
    Log.e(Db4oHelper.class.getName(), ie.getMessage());
    }
    }

    /**
    *  Cria uma nova instância de configuração
    * @return
    */
    private EmbeddedConfiguration config() {
    EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
    return configuration;
    }

    /**
    *
    * @param ctx
    * @return retorna o caminho da base
    */
    private String db4oDBFullPath(Context ctx) {
    return ctx.getDir("data", 0) + "/" + DATABASE_NAME;
    }

    public void commit() {
    database.commit();
    }

    public void rollBack() {
    database.rollback();
    }

    public void close() {
    if (this.database != null) {
    this.database.close();
    }
    }

    /**
    *
    * @return A data base para os providers utilizarem.
    */
    public ObjectContainer getDatabase() {
    return this.database;
    }
    }
    [/sourcecode]

    Após isso crie uma classe que estende o Db4pHelper, chamada PalavraProvider ela sera encarregada de disponibilizar os métodos de salvar, buscar todos, deletar todos.

    [sourcecode language="java"]
    package pedreiros_do_software.main;

    import java.util.List;
    import android.content.Context;

    public class PalavraProvider extends Db4oHelper {

    public PalavraProvider(Context ctx) {
    super(ctx);
    }

    public void salvar(Palavra palavra) {
    getDatabase().store(palavra);
    commit();
    }

    public void deletar(Palavra palavra) {
    getDatabase().delete(palavra);
    commit();
    }

    public List buscarTodos() {

    return getDatabase().query(Palavra.class);
    }

    public void deletarTodos(){
    List<Palavra> list = buscarTodos();

    for(Palavra p : list){
    deletar(p);
    }
    commit();
    }
    }

    [/sourcecode]

    O seu arquivo XML deve ficar como a figura a seguir:

    [sourcecode language="xml"]
    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <EditText
    android:id="@+id/et_palavra"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    </EditText>

    <Button
    android:id="@+id/bt_adicionar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Inserir" />

    <Button
    android:id="@+id/bt_buscar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Buscar Todos"/>

    <Button
    android:id="@+id/bt_deletar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Deletar Todos"/>

    <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#710200"
    android:id="@+id/linear_palavras"/>

    </LinearLayout>

    [/sourcecode]

    Com esse layout temos a nossa entrada de dados (Edittext), as funções de salvar e de deletar no respectivos Buttons  e um LinearLayout onde serão arpesentadas as strings.

    Com o layout criado vamos agora programar o funcionamento desta amazing tela!

    Abra a sua classe MainActivity declare todos os componentes e um Provider  e no método onCreate e  instancie a nossa classe PalavraProvider e todos os componentes que criamos no layout previamente, e adiciona o onclick nos botões. A seguir a classe. MainActivity.

    [sourcecode language="java"]
    import java.util.List;

    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    import android.app.Activity;
    import android.graphics.Color;

    public class MainActivity extends Activity {

    EditText edit;
    Button btInserir;
    Button btBuscar;
    Button btDeletar;
    PalavraProvider provider;
    LinearLayout linear;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    provider = new PalavraProvider(this);
    edit = (EditText) findViewById(R.id.et_palavra);
    btInserir = (Button) findViewById(R.id.bt_adicionar);
    btBuscar = (Button) findViewById(R.id.bt_buscar);
    btDeletar = (Button) findViewById(R.id.bt_deletar);
    linear = (LinearLayout) findViewById(R.id.linear_palavras);

    //Ação do botao inserir, insere o texto no do edittext na base
    btInserir.setOnClickListener(new View.OnClickListener() {

    public void onClick(View arg0) {
    Palavra palavra = new  Palavra();
    palavra.setTexto(edit.getText().toString());
    provider.salvar(palavra);

    }
    });

    //Ação do botao buscar, primeiro remove todas as palavras do linear em seguida busca todas as palavras na base
    //e por fim adiciona os textos no linear.
    btBuscar.setOnClickListener(new View.OnClickListener() {

    public void onClick(View v) {
    linear.removeAllViews();

    List<Palavra> list = provider.buscarTodos();

    if(!list.isEmpty()){
    TextView tv;

    for(Palavra p : list){
    tv = new TextView(getApplicationContext());
    tv.setText(p.getTexto());
    tv.setTextColor(Color.WHITE);
    linear.addView(tv);
    }
    }

    }
    });

    //Ação do botão deletar, remove todos os textos do linear e em seguida deleta todas as palavras da base.
    btDeletar.setOnClickListener(new View.OnClickListener() {

    public void onClick(View v) {
    linear.removeAllViews();

    provider.deletarTodos();
    }
    });

    }

    }

    [/sourcecode]

  • Resultados

    Como resultado pudemos observar o quão mais simples é criar e manter uma base puramente OO, se você estivesse criando essa estrutura com o banco relacional como o SQLite provavelmente demoraria muito mais tempo.

    Segue uma screenshot de como o projeto ficou.

    db4o example

    db4o example

    Como de praxe deixo aqui o link para download do projeto caso alguém tenha algum problema e precise consultar o código:
    https://github.com/cedulio/Android-Tutorial-Exemplo-db4o

Uma sugestão para deixar sua aplicação ainda melhor, utilize o padrão de design action bar. Que fornece ao usuário mais usabilidade e beleza, neste exemplo eu não utilizei a action bar para não misturar as coisas e assim facilitar o entendimento.

Caso você não conheça ou não faça idéia de como criar uma action bar na sua aplicação você pode visitar este outro post: https://pedreirosdosoftware-pedreiros.rhcloud.com/2012/08/04/android-action-bar-action-bar-sherlock/ no qual eu explico como criar uma action bar para aplicações 2.x.

Abraços e até a próxima.

19 thoughts on “[ TUTORIAL ] Android – Banco de dados db4o exemplo de como utilizar

    • Boa tarde Elias. Então eu nunca realizei essa operação. Se você tem o arquivo da base, joga ela dentro da pasta assets e tenta ler ele via código na primeira execução e inserir na tua base que fica no diretório que voce estipulou, e então apague esse arquivo via código da pasta assets.

  1. Parabéns pelo tutorial, esta muito simples e facil de implementar. Mas no meu caso, não sei se acontece com você ou não, mas sempre que o utilizador utiliza o “back button” e volta a entrar no programa, este estoira. Supostamente erro do acesso à BD pois aponta para um Null Pointer. Ja tentei tratar o back button para fazer um destroy() ou um finish(), mas sempre que saio e entro do programa sem voltar a compilar, da-me esse erro. Como posso prevenir isso?

        • Bom se você ja usa action bar, é só criar o seu botão no menu, interceptar o click do mesmo e a grosso modo colocar o codigo do botao inserir em um metodo para ser chamado pelo menu.

          O ideal é que se você vai salvar algo, você deve criar uma thread para fazer isso e tals, mas como não é ess eo foco do tutorial não falei sobre isso no post.

          • Estou fazendo assim:

            @Override
            public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
            //super.onCreateOptionsMenu(menu);
            MenuItem m1 = menu.add(0, 0, 0, “Nome do menu 1″);
            m1.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
            MenuItem m2 = menu.add(0, 1, 1, “Nome do menu 2″);
            m2.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
            MenuItem m3 = menu.add(0, 2, 2, “Nome do menu 3″);
            m3.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
            return;

            // inflater.inflate(R.menu.menu, menu); // Usar desse jeito caso o menu seja em xml

            }

            @Override
            public boolean onOptionsItemSelected(MenuItem item) {
            // Handle item selection
            switch (item.getItemId()) {
            case R.id.button1: // ID do seu ITEM
            // newGame(); // Método que deseja executar…
            Toast.makeText(MyFragmentA.this, “Clicou no botão”, Toast.LENGTH_SHORT).show();
            break;
            return true;
            default:
            return super.onOptionsItemSelected(item);
            }
            }

            Está dando esse erro em Toast.makeText:
            The method makeText(Context, CharSequence, int) in the type Toast is not applicable for the arguments (MyFragmentA, String, int)

  2. Frederico veja que a sua dúvida não tem muita relação com o que foi abordado no post.

    Mas de qualquer forma o problema é quando você está passando o MyFragmentA.this como primeiro parametro do makeText.

    Toast.makeText(MyFragmentA.this, “Clicou no botão”,Toast.LENGTH_SHORT).show();

    Tente ao invés de passar o MyFragmentA.this chamar o método getActivity() direto, ou então MyFragmentA.this.getActivity()

    Esse erro está acontecendo porque você está tentando passar um fragmento para um metodo que está esperando um context, no caso você precisa de uma activity para ter o contexto.

    • Fiz assim e deu esse erro agora:

      Toast.makeText(MyFragmentA.getActivity(), “Clicou no botão”, Toast.LENGTH_SHORT).show();

      Cannot make a static reference to the non-static method getActivity() from the type Fragment

        • Agora deu outro erro:

          @Override
          public boolean onOptionsItemSelected(MenuItem item) {
          // Handle item selection
          switch (item.getItemId()) {
          case R.id.button1: // ID do seu ITEM
          // newGame(); // Método que deseja executar…
          Toast.makeText(getActivity(), “Clicou no botão”, Toast.LENGTH_SHORT).show();
          break;
          return true;
          default:
          return super.onOptionsItemSelected(item);
          }
          }

          Sublinhou em vermelho:
          onOptionsItemSelected(MenuItem item)

          e return true;

          • Cara, você estão tentando dar um return true depois de executar o break…. coloque esse return pra fora do switch se é isso mesmo que você precisa.

    • Consegui arrumar, mas o Toast não aparece qdo clica em Nome do Menu 1 da Barra e sim no Botão1 do Fragment 3 que chama button1.

    • Com certeza, porem acredito que você vai precisar copiar ele da pasta assets para algum diretorio e então executar as suas rotinas neste novo arquivo, após isso apagar o arquivo.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>