quarta-feira, 11 de fevereiro de 2015

Android Sqlite Foreign Key

Android Sqlite Foreign Key


Neste tutorial mostrarei como usar a foreign key no Android, para isso criarei uma classe chamada Banco, essa classe será responsável por nos retornar uma conexão com o banco de dados SQLiteDatabase veja abaixo a classe banco.


package com.pds.teste.dao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by Renan on 03/02/2015.
 */
public class Banco {

    private final String BANCO = "banco.db";
    private final int BANCO_VERSAO = 1;
    private DbHelper dbHelper;



    class DbHelper extends SQLiteOpenHelper{


         public DbHelper(Context context) {
             super(context, BANCO, null, BANCO_VERSAO);
         }

         @Override
         public void onCreate(SQLiteDatabase db) {
             db.execSQL("CREATE TABLE IF NOT EXISTS Categoria  (_id INTEGER PRIMARY KEY AUTOINCREMENT,nome TEXT UNIQUE)");            
             db.execSQL("CREATE TABLE IF NOT EXISTS Produto  (_id INTEGER PRIMARY KEY AUTOINCREMENT,nome TEXT UNIQUE," +
                     "imagem text,descricao text,Categoria_id INTEGER , FOREIGN KEY(Categoria_id) REFERENCES Categoria(_id))");
             
         }

         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             //lista todas as tabelas a serem deletadas no on Upgrade
             String [] tabelas = {"Categoria","Produto","Lista","Lista_produto","Config","Itens_da_lista"};
             for(String table : tabelas){
                 db.execSQL("DROP TABLE IF EXISTS "+table);
                 onCreate(db);
             }

         }
     }

Nesse Exemplo estou criando duas tabelas uma de produtos e outra de categorias no final do create da tabela Produto crio uma Foreign Key em que a coluna Categoria_id  da tabela Produto referencia a coluna _id da tabela Categoria. Dessa forma quando tentarmos excluir uma categoria que tenha uma referência de um produto o sistema lançará um erro e nós poderemos pegar esse erro através de um bloco try catch, mas ainda não criamos o método da classe Banco que nos retorna uma conexão vejamos abaixo.

public SQLiteDatabase getConnection(Context context){
        dbHelper = new DbHelper(context);
        SQLiteDatabase sqLiteDatabase = dbHelper.getWritableDatabase();
        
    }

Com esse método retornamos um objeto do tipo SQLitesDatabase e com ele podemos fazer qualquer procedimento sql chamando o método execSQL() desse objeto, agora podemos criar nosso crude  utilizando essa conexão, porém ainda temos um problema com a nossa foreign key pois mesmo com a nossa implementação no create table ela não funcionará, aí você me pergunta porquê? Bem essa é uma resposta fácil, o Android vem por padrão com as foreign keys desativadas , ou seja, você vai precisar ativa-las, mas não se preocupe isso é fácil de resolver, para isso precisamos executar um comando sql para fazer a ativação, vamos aproveitar o código do método acima para que toda vez que retornarmos uma conexão a foreign key já venha ativada, veja o código abaixo.

public SQLiteDatabase getConnection(Context context){
        dbHelper = new DbHelper(context);
        SQLiteDatabase sqLiteDatabase = dbHelper.getWritableDatabase();
        sqLiteDatabase.execSQL("PRAGMA foreign_keys=ON;");
        return sqLiteDatabase;
    }

Agora sim com esse comando sql ativamos a foreign key, como você pode notar chamamos o método execSQL() do objeto sqLiteDatabase e executamos nosso primeiro comando sql, agora tudo que você precisa para criar seu crude é chamar o método getConnection() da classe banco e criar seus inserts , deletes etc. Lembrando que o método que vai deletar categoria lançará uma SQLiteConstraintException se você tentar remover uma categoria que esteja sendo referenciada por um produto. Segue o código completo da classe Banco.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.pds.teste.dao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by Renan on 03/02/2015.
 */
public class Banco {

    private final String BANCO = "banco.db";
    private final int BANCO_VERSAO = 1;
    private DbHelper dbHelper;



    class DbHelper extends SQLiteOpenHelper{


         public DbHelper(Context context) {
             super(context, BANCO, null, BANCO_VERSAO);
         }

         @Override
         public void onCreate(SQLiteDatabase db) {
             db.execSQL("CREATE TABLE IF NOT EXISTS Categoria  (_id INTEGER PRIMARY KEY AUTOINCREMENT,nome TEXT UNIQUE)");            
             db.execSQL("CREATE TABLE IF NOT EXISTS Produto  (_id INTEGER PRIMARY KEY AUTOINCREMENT,nome TEXT UNIQUE," +
                     "imagem text,descricao text,Categoria_id INTEGER , FOREIGN KEY(Categoria_id) REFERENCES Categoria(_id))");
             
         }

         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             //lista todas as tabelas a serem deletadas no on Upgrade
             String [] tabelas = {"Categoria","Produto","Lista","Lista_produto","Config","Itens_da_lista"};
             for(String table : tabelas){
                 db.execSQL("DROP TABLE IF EXISTS "+table);
                 onCreate(db);
             }

         }
     }

    public SQLiteDatabase getConnection(Context context){
        dbHelper = new DbHelper(context);
        SQLiteDatabase sqLiteDatabase = dbHelper.getWritableDatabase();
        sqLiteDatabase.execSQL("PRAGMA foreign_keys=ON;");
        return sqLiteDatabase;
    }
}