Android SQLite Kullanımı

Zekeriya Dönmez
5 min readSep 28, 2023

--

Android uygulamaları geliştirirken uygulamamızın bir noktasında veri depolama ihtiyacı duyabiliriz. Öncelikle depolayacağımız veriyi cihaz hafızasında mı yoksa çevrimiçi olarak mı tutacağımızı belirlememiz gerekiyor. Eğer cihaz hafızasında veri depolamayı planlıyorsanız kullanabileceğiniz birkaç alternatif yapı var, bu yazımda bunlardan biri olan SQLite hakkında sizlere bilgi aktaracağım.

SQLite Kurulumu ve Kullanımı
Öncelike cihaz içerisinde veri depolayacağımız için Manifest dosyası içerisinde gerekli olan izni vermemiz gerekiyor.
<manifest> tag’inin altında <application> tag’inin üzerinde izin için gerekli olan şu kodumuzu ekliyoruz.

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

// Eklememiz gereken izin kodu
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />

<application>
.
.
.
</application>

</manifest>

Manifest dosyası ile işimiz bitti, sırada veritabanı işlemleri için kullanacağımız yardımcı sınıfı oluşturmak var.

DatabaseHelper.kt isminde bir dosya oluşturuyoruz ve SQLiteOpenHelper sınıfını oluşturduğumuz bu sınıfa implement ediyoruz.

DatabaseHelper.kt

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

class DatabaseHelper(val context: Context) : SQLiteOpenHelper(context,"VeritabaniIsmi",null,1) {
override fun onCreate(db: SQLiteDatabase?) {
// Veritabanı oluşturulduğunda ilk çalışacak metod
}

override fun onUpgrade(db: SQLiteDatabase?, p1: Int, p2: Int) {
// Veritabanı güncellemesi yapıldığı zaman çalışacak metod
}
}

SQLiteOpenHelper soyut sınıfı parametre olarak 3 tane değer alıyor.
1. parametremiz context değeridir.
2. parametremiz oluşturacağımız veritabanının ismidir.
3. parametre CursorFactory parametresi, bu parametre eğer özel olarak bir Cursor sınıfı oluşturduysak gerekli ben null olarak girdim, varsayılan CursorFactory’i kullandım
4. parametre veritabanı versiyonu’dur. Veritabanında değişiklik yaptıkça bu sayıyı değiştirebiliriz.

Üstteki attığım kodda farkettiğiniz üzere override edilmiş 2 metod bulunuyor, bu metodların görevleri şu şekilde;

onCreate metodu: Veritabanını oluşturulduğumuzda çalışacak ilk metoddur aynı şekilde burada veritabanında kullanacağımız tabloları da oluşturduğumuz metoddur.

onUpgrade metodu: Veritabanı yapısında bir değişiklik yaptığımızda çalışacak metoddur.

Peki bu metodları oluşturduk içerilerini nasıl dolduracağız bunu açıklayalım.

DatabaseHelper.kt

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

class DatabaseHelper(val context: Context) : SQLiteOpenHelper(context,"VeritabaniIsmi",null,1) {
override fun onCreate(db: SQLiteDatabase?) {
val createTableQuery = """
CREATE TABLE personeller(
personel_id INTEGER PRIMARY KEY AUTOINCREMENT,
personel_ad VARCHAR(45),
personel_gorev VARCHAR(45),
personel_yas INTEGER
)
""".trimIndent()
db?.execSQL(createTableQuery)
}

override fun onUpgrade(db: SQLiteDatabase?, p1: Int, p2: Int) {
db?.execSQL("DROP TABLE IF EXISTS personeller")
onCreate(db)
}
}

onCreate içerisinde veritabanında kullanacağımız tabloları oluşturuyoruz.
SQLiteDatabase sınıfından türemiş db parametremizin execSQL komutunu kullanarak SQL kodumuzu çalıştırıyoruz, execSQL’e ise parametre olarak bir SQL cümleciği veriyoruz, buradaki verdiğimiz cümlecik tablo oluşturmak için kullandığımız SQL cümleciği olacak.

onUpgrade metodu içerisinde ise veritabanında bir problem çıkması veya veritabanının güncellenmesi durumunda çalıştıracağımız SQL cümleciğini execSQL metodu ile çalıştırıp varolan tabloyu siliyoruz ardından tabloyu yeniden oluşturmak için onCreate metodunu çalıştırıyoruz.

Buraya kadarki oluşturduğumuz kod bizim için temel altyapıyı sağlayacak.
Veritabanı işlemler için gerekli metodları yazmadan önce veritabanında oluşturduğumuz tablo için bir model sınıfı yazalım.

Personel.kt

data class Personel(
val id: Int,
val ad: String,
val gorev: String,
val yas: Int
)

Daha sonra veritabanı işlemlerini yapabilmek için bu sınıfa ait DAO(Database Access Object) sınıfımızı yazalım.

PersonelDao.kt

import android.annotation.SuppressLint
import android.content.ContentValues

class PersonelDao(val dbHelper: DatabaseHelper) {

// Tabloya kayıt ekleme
fun personelEkle(personelAd: String, personelGorev: String, personelYas: Int) {
// DbHelper sınıfından yazılabilir bir veritabanı alıyoruz.
val writableDatabase = dbHelper.writableDatabase
/* Yazacagımız kayıt için gerekli olan alanları parametredeki
girdiğimiz veriler ile eşitliyoruz */
val contentValues = ContentValues()
contentValues.apply {
put("personel_ad", personelAd)
put("personel_gorev", personelGorev)
put("personel_yas", personelYas)
}
// Kayıt işlemini gerçekleştiriyoruz
writableDatabase.insert(
"personeller", // Kayıt ekleceğimiz tablo
null, // Null olarak geçeceğimiz sütunları belirttiğimiz alan
contentValues)
// Kayıt işlemi bittikten sonra veritabanını kapatıyoruz.
writableDatabase.close()
}

// Tablodaki kaydı güncelleme
fun personelGuncelle(
personelId: Int,
yeniPersonelAd: String,
yeniPersonelGorev: String,
yeniPersonelYas: Int
) {
// DbHelper sınıfından yazılabilir bir veritabanı alıyoruz.
val writableDatabase = dbHelper.writableDatabase
/* Güncelleyecegimiz kayıt için gerekli olan alanları parametredeki
girdiğimiz veriler ile esitliyoruz */
val contentValues = ContentValues()
contentValues.apply {
put("personel_ad", yeniPersonelAd)
put("personel_gorev", yeniPersonelGorev)
put("personel_yas", yeniPersonelYas)
}
// Güncelleme işlemini gerçekleştiriyoruz
writableDatabase.update(
"personeller", // Güncelleyeceğimiz tablo ismi
contentValues, // Güncel veriler
"personel_id = ?", // Güncellenecek alan için gerekli koşul
arrayOf(personelId.toString()) // ? yerine gelecek veri
)
}

// Tablodaki kayıtları okuma
@SuppressLint("Range")
fun personelleriGetir(): List<Personel> {
val readableDatabase = dbHelper.readableDatabase
val personeller = readableDatabase.rawQuery(
"SELECT * FROM personeller", // Bütün kayıtları getirmek için gerekli olan SQL cümleciği
null, // ? olarak belirttiğimiz alanlar yerine geçecek değerler (bizim sql cümlecğimizde yok)
null
)
val personelListesi = ArrayList<Personel>()
// personeller listesini geziyoruz
personeller.apply {
while (moveToNext()) {
val personelId = getInt(getColumnIndex("personel_id"))
val personelAd = getString(getColumnIndex("personel_ad"))
val personelGorev = getString(getColumnIndex("personel_gorev"))
val personelYas = getInt(getColumnIndex("personel_yas"))
val personel = Personel(personelId, personelAd, personelGorev, personelYas)
personelListesi.add(personel)
}
}
readableDatabase.close()
return personelListesi
}

// Tablodaki kaydı silme
fun personelSil(personelId: Int) {
val writableDatabase = dbHelper.writableDatabase
writableDatabase.delete(
"personeller", // Veriyi sileceğimiz tablonun ismi
"personel_id = ?", // Silinecek veri için gerekli koşul
arrayOf(personelId.toString()) // Koşul içindeki ? yerine gelecek değer
)
writableDatabase.close() // Veritabanını kapatıyoruz
}
}

Bu şekilde sınıfımızı oluşturduktan sonra sıra geldi test etmeye, testi MainActivity.kt üzerinde yapacağım.

MainActivity.kt

package com.zecky.mediumsqlite

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val dbHelper = DatabaseHelper(this)
val personelDao = PersonelDao(dbHelper)

/* PersonelDao sınıfından personelEkle metodunu çağırıp 3 adet
kayıt ekliyorum */
personelDao.personelEkle("Zekican","Bilgisayar Mühendisi",24)
personelDao.personelEkle("Ceren","Makine Mühendisi",32)
personelDao.personelEkle("Okan","Diş Hekimi",28)

}
}

Gördüğünüz üzere PersonelDao sınıfından oluşturduğumuz objeyi kullanarak 2 adet kaydı veritabanımıza ekledik, bu veritabanını görüntüleyelim.

Oluşturduğumuz veritabanı dosyasına görüntülemek için (veritabanını içerisine herhangi bir veri ekledikten sonra)! Android studio içerisinde bulunan Device Explorer kısmından uygulamamızın dosya konumuna geldiğimizde databases klasörü içerisinden ulaşabiliriz.

Veritabanı dosyasını bulduktan sonra üzerine sağ tıklayıp “Save As” dedikten sonra eklediğimiz kayıtları görüntülemek için çevrimiçi sqlite görüntüleyen bu sitede kayıtlarımızı kontrol edelim.

Eklenen Kayıtların Görüntülenmesi

Gördüğünüz üzere bu sqlite dosyası eklediğimiz 3 kaydı içeriyor. Yaptığımız işlem başarılı oldu. 🎉

Ekleme işlemini gerçekleştirdiğimize göre sırada güncelleme işlemini yapalım, 2 numaralı kaydımızdaki kişi ismini Ceren yerine Ayşe ile değiştirelim.

MainActivity.kt

package com.zecky.mediumsqlite

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val dbHelper = DatabaseHelper(this)
val personelDao = PersonelDao(dbHelper)

personelDao.personelGuncelle(2,"Ayşe","Makine Mühendisi",32)

}
}
Güncellenmiş Kayıtlar Tablosu

Gördüğünüz üzere 2 nolu kaydımızı güncelledik.

Güncelleme işlemini de başarıyla yaptığımıza göre sırada silme işlemini gerçekleştirelim 3 nolu kaydı tablodan silmeyi deneyelim.

MainActivity.kt

package com.zecky.mediumsqlite

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val dbHelper = DatabaseHelper(this)
val personelDao = PersonelDao(dbHelper)
personelDao.personelSil(3)



}
}
Yeni Kayıtlı Personel Tablosu

Gördüğünüz üzere 3 numaradaki kaydı sildik, yeni tablomuz üstteki şekilde oldu. Sırada var olan bütün kayıtları görüntülemeye geldi.

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val dbHelper = DatabaseHelper(this)
val personelDao = PersonelDao(dbHelper)
val personeller = personelDao.personelleriGetir()
println(personeller)


}
}
Okuduğumuz Bütün Kayıtlar

Bütün kayıtlarımızı yazdırdık, Personel sınıfını Data Class olarak tanımladığımız için okunaklı bir biçimde bize sınıf nesnelerimizi verdi.

Bu yazımda anlatacaklarım bu kadardı. Buraya kadar okuyanlara ayrıca teşekkür etmek istiyorum, iyi çalışmalar dilerim 😊

--

--

Zekeriya Dönmez

Öğrendiklerini başkalarıyla paylaşmayı seven bir bilgisayar mühendisliği öğrencisi ve mobil geliştirici.