Mobil Programlama

Android

DERS PROGRAMI
Android 301 Ders Programı

Verileri SQL Veritabanına Kaydetmek

Lisans: Creative Commons 26.11.2020 tarihinde güncellendi
Bakabileceğiniz Etiketler: Eğitmen: Geleceği Yazanlar Ekibi

Sürekli tekrarlayan veya kişi bilgileri gibi belli bir yapısı olan verileri, veritabanına kaydetmek iyi bir karardır. Veritabanı sayesinde verileriniz üzerinde şartlı işlemler yapabilir, onları daha iyi yönetebilirsiniz. Bu eğitim içeriğinde SQL veritabanlarının geneline aşina olduğunuzu varsayıyoruz. Android üzerinde SQLite veritabanlarını öğrenmeye başlarken bu aşinalık size yardımcı olacaktır.

Android üzerinde SQLite veritabanı için ihtiyacınız olan API'ler android.database.sqlite paketi içinde olacaktır.
 

Şemayı ve kontratı tanımlamak

SQL veri tabanlarının ana ilkelerinden biri de şemadır. Şema, veritabanının nasıl organize edildiğinin biçimsel bir açıklamasıdır. Şema, veritabanınızı oluşturmakta kullanacağınız SQL ifadelerinden oluşan bir yansımadır. Şemanızın yapısını sistematik bir yolla ifade eden bir "kontrat" sınıfı yazmak bu konuda yararınıza olacaktır.

Bir kontrat sınıfı* tablolar, sütunlar ve URI'ler için isim tanımlamaları yapan sabitleri bulunduran bir taşıyıcı gibidir. Kontrat sınıfı* sayesinde aynı sabitleri uygulama paketiniz içindeki diğer sınıflarda da kullanabilirsiniz. Bu size örneğin bir sütun ismini değiştirdiğinizde bunu tüm kodunuzda değiştirmenize gerek vermez ve zahmetsizce kullanabilmenizi sağlar.

Kontrat sınıfı oluşturmanın iyi bir yolu da veritabanınızın global tanımlamalarını sınıf seviyesinde değişkenler şeklinde koymaktır. Ardından her tablo için bir dâhili (inner) sınıf oluşturmak ve bu sınıflara sütun isimlerine karşılık gelecek şekilde numaralandırma yapmak gayet iyi bir kullanım şeklidir. Bunun ayrıntılarını belgenin ilerleyen bölümlerinde görebilirsiniz.

NOT: BaseColumns arayüzünü (interface) gerçeklerseniz (implementation), dâhili sınıflarınızın _ID olarak anılan birincil anahtar alanlarını miras almasını sağlayabilirsiniz. Android'in cursor adapter gibi bazı sınıfları _ID gibi alanlar ile çalıştığından bu uyumluluk açısından size kolaylık sağlar. Elbette şart değildir, ancak veritabanınızın Android geliştirme çatısı (framework) ile uyumlu çalışması epey işinize gelecektir.

Aşağıdaki örnekte, tek bir tablonun adını ve sütun adlarını tanımlayan bir örnek kod görüyorsunuz:

public final class FeedReaderContract {
    // birinin bu sınıfı yanlışlıklar örneklemesinin önüne geçmek için yapılandırıcı metodu boş bırakıyoruz
    public FeedReaderContract() {}

    /* tablo içeriklerini tanımlayan dahili sınıflar */
    public static abstract class FeedEntry implements BaseColumns {
        public static final String TABLE_NAME = "entry";
        public static final String COLUMN_NAME_ENTRY_ID = "entryid";
        public static final String COLUMN_NAME_TITLE = "title";
        public static final String COLUMN_NAME_SUBTITLE = "subtitle";
        ...
    }
}

 

SQL Helper kullanarak veritabanı oluşturmak

Veritabanınızın nasıl olacağını tanımladığınıza göre artık veritabanınızı (tablolarını) oluşturacak ve onun çalışmasını sürdürecek metotları da gerçeklemelisiniz. Aşağıda bu amaçla yazılmış tipik SQL ifadelerini görebilirsiniz. Bir tablo oluşturan ve eğer o tablo varsa önce kaldıran iki String ifadesi oluşturuluyor:

private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
    "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
    FeedEntry._ID + " INTEGER PRIMARY KEY," +
    FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
    FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
    ... // CREATE komutuyla ilgili diğer seçenekler
    " )";

private static final String SQL_DELETE_ENTRIES =
    "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;

Tıpkı cihazın dâhili depolama alanına kaydettiğiniz dosyalar için olduğu gibi veritabanlarınız da uygulamayla ilişkili özel bir disk alanına kaydedilir. Verileriniz güvenli bir yerdedir çünkü bu alan diğer uygulamalar tarafından erişilebilir bir konumda değildir.

Veritabanı işleri için kullanışlı ve işinizi hızlandıracak bir API serisi SQLiteOpenHelper sınıfı içinde bulunuyor. Veritabanınız için bu sınıftan bir referans aldığınızda yani onu kullanmaya başladığınızda, sistem muhtemelen uzun sürecek veritabanı oluşturma ve güncelleme gibi işlemleri sadece ihtiyaç olduğunda gerçekleştirecektir, uygulama başlangıcında değil. Tüm ihtiyacınız olan şey, getWritableDatabase() veya getReadableDatabase() metotlarını çağırmak.

NOT: Uzun süren işlemler yaptıkları için getWritableDatabase() veya getReadableDatabase() metotlarını arkaplandaki bir thread'te (AsyncTask veya IntentService ile) çalıştırdığınızdan emin olmalısınız.

SQLiteOpenHelper'ı kullanmak için onCreate(), onUpgrade() ve onOpen() gibi callback metotlarını ezen (override) bir alt sınıf oluşturmalısınız. onDownGrade() metodunu da gerçeklemek isteyebilirsiniz ancak gerek olmayacaktır.

Aşağıdaki örnekte SQLiteOpenHelper'ın temel komutlarını kullanan bir sınıfı görebilirsiniz:

public class FeedReaderDbHelper extends SQLiteOpenHelper {
// eğer veritabanı şemanızı değiştirirseniz bu sürüm değişkenini mutlaka artırmalısınız
   public static final int DATABASE_VERSION = 1;
   public static final String DATABASE_NAME = "FeedReader.db";

   public FeedReaderDbHelper(Context context) {
       super(context, DATABASE_NAME, null, DATABASE_VERSION);
   }

   public void onCreate(SQLiteDatabase db) {
       db.execSQL(SQL_CREATE_ENTRIES);
   }

   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   // örnekteki bu veritabanı çevrimiçi sitedeki verileri önbelleklemek için kullanılacak. bu yüzden yükseltme gerektiğinde var olan verileri atıp, yenileriyle başlayabilmeliyiz
       db.execSQL(SQL_DELETE_ENTRIES);
       onCreate(db);
   }

   public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
       onUpgrade(db, oldVersion, newVersion);
   }
}

Veritabanınıza erişmek için SQLiteOpenHelper'ın bir alt sınıfını örneklemeniz yeterli:

FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());

 

Veritabanına bilgileri kaydetmek

Veritabanına verileri eklemek için bir ContentValues nesnesini parametre olarak insert() metoduna geçmeniz yeterli:

// veri depomuza yazılabilir modda ulaşalım
SQLiteDatabase db = mDbHelper.getWritableDatabase();

// ekleyeceğimiz verileri bir map nesnesi şeklinde, sütun adları anahtar olarak oluşturalım
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_CONTENT, content);

// yeni bir satır ekleyelim ve yeni satırın birincil anahtar değerini döndürelim

long newRowId;
newRowId = db.insert(
        FeedEntry.TABLE_NAME,
        FeedEntry.COLUMN_NAME_NULLABLE,
        values);

insert() metodunun ilk parametresi tablo adıdır. İkinci parametre sütun adı yerine gelir ve veritabanı altyapısı eğer ContentValues boşsa buraya NULL değer verebilir ve böylece eklenecek değer olmadığında buraya yeni bir satır eklemez.

 

Veritabanından bilgileri okumak

Veritabanından bilgileri okumak için

Cursor içindeki satırlara bakmak için (değerleri okumaya başlamadan önce mutlaka çağırmanız gereken) nesnenin içinde gezmenize yarayan metotlardan birini kullanmalısınız. Genellikle moveToFirst() metodunu çağırarak başlamalısınız. Bu metot sonuçlar içindeki ilk girdinin "okuma pozisyonu"nun (read position) yerini sağlar. Her satırda Cursor'un get metotlarından birini (getString(), getLong() gibi) kulanarak sütunun oradaki değerini okuyabilirsiniz. Her get metoduna istediğiniz sütunun indeks posizyonunu parametre olarak geçmeniz gerekir. Bu indeks pozisyonunu getColumnIndex() veya getColumnIndexOrThrow() metotlarını kullanarak alabilirsiniz. Örnek:

cursor.moveToFirst();
long itemId = cursor.getLong(
   cursor.getColumnIndexOrThrow(FeedEntry._ID)
);

 

Veritabanından bilgileri silmek

Bir tablodaki satırları silmek için silmek o satırları ifade eden seçim kriterini de yazmanız gerekiyor. Android veritabanı API'si seçim kriterleri oluşturmak ve SQL sızmasını (injection) önlemek için bir mekanizma sağlıyor. Bu mekanizma sayesinde seçimi ifade eden kriter, parametreler ve seçim cümleciği olarak ayrılıyor. Seçim cümleciği, ilgilendiğiniz-silmek istediğiniz sütunları tanımladığınız yer oluyor. Parametreler ise değerler oluyor. Sonuç düzenli bir SQL ifadesiyle aynı şekilde yönetilmediği için SQL zehirlemesine karşı bir bağışıklık kazanılıyor.

// Sorgunun ‘where' kısmını tanımlayalım
String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?";
// Parametreleri sırasıyla tanımlayalım
String[] selectionArgs = { String.valueOf(rowId) };
// SQL ifadesini çalıştıralım
db.delete(table_name, selection, selectionArgs);

 

Veritabanında güncelleme yapmak

Veritabanınızdaki belli bir küme veriyi değiştirmek istediğinizde

Bu eğitim içeriğinin orijinal hâline buradan ulaşabilirsiniz: Saving Data in SQL Databases