Verileri veritabanına kaydetmek, iletişim bilgileri gibi tekrarlanan veya yapılandırılmış veriler için idealdir. Bu sayfada, genel olarak SQL veritabanlarına aşina olduğunuz varsayılır ve Android'de SQLite veritabanlarını kullanmaya başlamanıza yardımcı olunur. Android'de veritabanı kullanmak için ihtiyaç duyacağınız API'ler android.database.sqlite
paketinde bulunur.
Dikkat: Bu API'ler güçlü olsa da oldukça düşük düzeydedir ve kullanımı çok fazla zaman ve çaba gerektirir:
- Ham SQL sorguları için derleme zamanı doğrulaması yoktur. Verileriniz değiştikçe etkilenen SQL sorgularını manuel olarak güncellemeniz gerekir. Bu işlem zaman alıcı ve hataya açık olabilir.
- SQL sorguları arasında dönüşüm yapmak için çok sayıda standart kod kullanmanız gerekir. ve veri nesnelerinden bahsedeceğiz.
Bu nedenlerle, Kesinlikle Odada Kalıcılık Kitaplığı uygulamanızın SQLite'ındaki bilgilere erişmek için bir soyutlama katmanı olarak veri tabanları.
Şema ve sözleşme tanımlama
SQL veritabanlarının ana ilkelerinden biri şemadır: nasıl düzenlendiğini gösteren açıklamadır. Şema, veritabanınızı oluşturmak için kullandığınız SQL ifadelerine yansıtılır. Ekibiniz ve sizin için sözleşme sınıfı olarak bilinen ve açıkça belirten bir tamamlayıcı sınıf oluşturun. kendi kendini belgeleyen bir yöntemle düzenlemenizi sağlar.
Sözleşme sınıfı, URI'ların adlarını tanımlayan sabit değerler için bir kapsayıcıdır. tablo ve sütun yer alır. Sözleşme sınıfı, aynı sabit değerleri kullanmanıza olanak tanır aynı paketteki diğer tüm sınıflarda oluşturabilirsiniz. Bu özellik, sütununuzda kodunu tek bir yere toplamanızı ve bu adın kodunuza uygulanmasını sağlar.
Sözleşme sınıfını düzenlemenin iyi bir yolu, tüm veritabanınız için genel olan tanımları sınıfın kök düzeyine yerleştirmektir. Sonra iç içe bir sınıfını kullanır. Her iç sınıf, ilgili tablonun sütunlarını listeler.
Not: BaseColumns
uygulayarak
bir sonraki aşamaya geçiş yaparsanız, iç sınıfınız birincil
temel alan _ID
, CursorAdapter
gibi bazı Android sınıflarında Zorunlu değildir ancak bu, veritabanınızın Android çerçevesiyle uyumlu çalışmasına yardımcı olabilir.
Örneğin, aşağıdaki sözleşmede bir RSS özet akışını temsil eden tek bir tablo:
Kotlin
object FeedReaderContract { // Table contents are grouped together in an anonymous object. object FeedEntry : BaseColumns { const val TABLE_NAME = "entry" const val COLUMN_NAME_TITLE = "title" const val COLUMN_NAME_SUBTITLE = "subtitle" } }
Java
public final class FeedReaderContract { // To prevent someone from accidentally instantiating the contract class, // make the constructor private. private FeedReaderContract() {} /* Inner class that defines the table contents */ public static class FeedEntry implements BaseColumns { public static final String TABLE_NAME = "entry"; public static final String COLUMN_NAME_TITLE = "title"; public static final String COLUMN_NAME_SUBTITLE = "subtitle"; } }
SQL yardımcısı kullanarak veritabanı oluşturma
Veritabanınızın nasıl göründüğünü tanımladıktan sonra, veritabanı ve tabloları oluşturup yöneten Tablo oluşturan ve silen bazı tipik ifadeler aşağıda verilmiştir:
Kotlin
private const val SQL_CREATE_ENTRIES = "CREATE TABLE ${FeedEntry.TABLE_NAME} (" + "${BaseColumns._ID} INTEGER PRIMARY KEY," + "${FeedEntry.COLUMN_NAME_TITLE} TEXT," + "${FeedEntry.COLUMN_NAME_SUBTITLE} TEXT)" private const val SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS ${FeedEntry.TABLE_NAME}"
Java
private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" + FeedEntry._ID + " INTEGER PRIMARY KEY," + FeedEntry.COLUMN_NAME_TITLE + " TEXT," + FeedEntry.COLUMN_NAME_SUBTITLE + " TEXT)"; private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
Tıpkı cihazın dahili klasörüne kaydettiğiniz dosyalar gibi depolama alanı kullanıyorsanız Android, veritabanınızı uygulamanızın gizli klasöründe depolar. Varsayılan olarak bu alana diğer uygulamalar veya kullanıcı erişemediğinden verileriniz güvendedir.
SQLiteOpenHelper
sınıfı yararlı bir
API seti kullanıma hazırdır.
Veritabanınıza referanslar almak için bu sınıfı kullandığınızda sistem,
gerçeğe dönüştüğü takdirde
veri tabanı oluşturma ve güncelleme gibi uzun süreli işlemleri, yalnızca
uygulama başlatılırken değil. Tek yapmanız gereken telefon görüşmesi yapmak
getWritableDatabase()
veya
getReadableDatabase()
.
Not: Uzun süreli olabileceği için
bir arka plan ileti dizisinde getWritableDatabase()
veya getReadableDatabase()
adını belirttiğinizden emin olun.
Daha fazla bilgi için Android'de ileti dizisi bölümüne göz atın.
SQLiteOpenHelper
kullanmak için onCreate()
ve onUpgrade()
geri çağırma yöntemlerini geçersiz kılan bir alt sınıf oluşturun. onDowngrade()
veya onOpen()
yöntemlerini de uygulayabilirsiniz ancak bu zorunlu değildir.
Örneğin burada, şöyle bir SQLiteOpenHelper
aşağıda gösterilen komutların bazılarını kullanır:
Kotlin
class FeedReaderDbHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { override fun onCreate(db: SQLiteDatabase) { db.execSQL(SQL_CREATE_ENTRIES) } override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { // This database is only a cache for online data, so its upgrade policy is // to simply to discard the data and start over db.execSQL(SQL_DELETE_ENTRIES) onCreate(db) } override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { onUpgrade(db, oldVersion, newVersion) } companion object { // If you change the database schema, you must increment the database version. const val DATABASE_VERSION = 1 const val DATABASE_NAME = "FeedReader.db" } }
Java
public class FeedReaderDbHelper extends SQLiteOpenHelper { // If you change the database schema, you must increment the database version. 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) { // This database is only a cache for online data, so its upgrade policy is // to simply to discard the data and start over 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 alt sınıfınızı örneklendirin:
SQLiteOpenHelper
:
Kotlin
val dbHelper = FeedReaderDbHelper(context)
Java
FeedReaderDbHelper dbHelper = new FeedReaderDbHelper(getContext());
Bilgileri bir veritabanına ekleme
insert()
yöntemine bir ContentValues
nesnesi göndererek veritabanına veri ekleyin:
Kotlin
// Gets the data repository in write mode val db = dbHelper.writableDatabase // Create a new map of values, where column names are the keys val values = ContentValues().apply { put(FeedEntry.COLUMN_NAME_TITLE, title) put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle) } // Insert the new row, returning the primary key value of the new row val newRowId = db?.insert(FeedEntry.TABLE_NAME, null, values)
Java
// Gets the data repository in write mode SQLiteDatabase db = dbHelper.getWritableDatabase(); // Create a new map of values, where column names are the keys ContentValues values = new ContentValues(); values.put(FeedEntry.COLUMN_NAME_TITLE, title); values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle); // Insert the new row, returning the primary key value of the new row long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);
insert()
için ilk bağımsız değişken
tablo adıdır.
İkinci bağımsız değişken, ContentValues
boş olduğunda (yani herhangi bir değer put
vermediğinizde) çerçeveye ne yapacağını söyler.
Bir sütunun adını belirtirseniz çerçeve bir satır ekler ve bu sütunun değerini null olarak ayarlar. Bu kod örneğinde olduğu gibi null
belirtirseniz çerçeve, değer olmadığında satır eklemez.
insert()
yöntemleri, yeni oluşturulan satırın kimliğini döndürür veya verileri eklerken hata oluştuysa -1 döndürür. Bu durum, veritabanındaki önceden var olan verilerle çakışma yaşıyorsanız ortaya çıkabilir.
Veritabanındaki bilgileri okuma
Bir veritabanından okumak için query()
yöntemini kullanın. Bu yönteme seçim ölçütlerinizi ve istediğiniz sütunları iletin.
Yöntem, insert()
ve update()
öğelerini birleştirir. Bununla birlikte, sütun listesi, eklenecek veriler yerine getirmek istediğiniz verileri ("projeksiyon") tanımlar. Sonuçlar
bir Cursor
nesnesinde size döndürülür.
Kotlin
val db = dbHelper.readableDatabase // Define a projection that specifies which columns from the database // you will actually use after this query. val projection = arrayOf(BaseColumns._ID, FeedEntry.COLUMN_NAME_TITLE, FeedEntry.COLUMN_NAME_SUBTITLE) // Filter results WHERE "title" = 'My Title' val selection = "${FeedEntry.COLUMN_NAME_TITLE} = ?" val selectionArgs = arrayOf("My Title") // How you want the results sorted in the resulting Cursor val sortOrder = "${FeedEntry.COLUMN_NAME_SUBTITLE} DESC" val cursor = db.query( FeedEntry.TABLE_NAME, // The table to query projection, // The array of columns to return (pass null to get all) selection, // The columns for the WHERE clause selectionArgs, // The values for the WHERE clause null, // don't group the rows null, // don't filter by row groups sortOrder // The sort order )
Java
SQLiteDatabase db = dbHelper.getReadableDatabase(); // Define a projection that specifies which columns from the database // you will actually use after this query. String[] projection = { BaseColumns._ID, FeedEntry.COLUMN_NAME_TITLE, FeedEntry.COLUMN_NAME_SUBTITLE }; // Filter results WHERE "title" = 'My Title' String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?"; String[] selectionArgs = { "My Title" }; // How you want the results sorted in the resulting Cursor String sortOrder = FeedEntry.COLUMN_NAME_SUBTITLE + " DESC"; Cursor cursor = db.query( FeedEntry.TABLE_NAME, // The table to query projection, // The array of columns to return (pass null to get all) selection, // The columns for the WHERE clause selectionArgs, // The values for the WHERE clause null, // don't group the rows null, // don't filter by row groups sortOrder // The sort order );
Üçüncü ve dördüncü bağımsız değişkenler (selection
ve selectionArgs
)
bir WHERE ifadesi oluşturmak için kullanılır. Seçim sorgusundan ayrı olarak sağlanan bağımsız değişkenler, birleştirilmeden önce kaçılır. Bu sayede seçim ifadeleriniz SQL ekleme saldırılarına karşı korunur. Tüm bağımsız değişkenler hakkında daha fazla bilgi için
query()
referansı.
İmleçteki bir satırı görmek için Cursor
taşıma işlemlerinden birini kullanın
yöntemleri kullanır. Bunlar, değerleri okumaya başlamadan önce her zaman çağırmanız gerekir. İmleç -1 konumunda başladığından moveToNext()
çağrıldığında "okuma konumu" sonuçlardaki ilk girişe yerleştirilir ve imlecin sonuç kümesinin son girişini geçip geçmediği döndürülür. Her satır için
Cursor
, getString()
veya getLong()
gibi yöntemleri alır. Get yöntemlerinin her biri için, istediğiniz sütunun dizin konumunu iletmeniz gerekir. Bu konumu getColumnIndex()
veya getColumnIndexOrThrow()
'i çağırarak alabilirsiniz. Tamamlandığında
sonuçlar yineleniyor, imleçte close()
işlevini çağırın
serbest bırakılmasını isteyebilirsiniz.
Örneğin, aşağıdaki örnekte bir imleçte depolanan tüm öğe kimliklerinin nasıl alınacağı ve bir listeye nasıl ekleneceği gösterilmektedir:
Kotlin
val itemIds = mutableListOf<Long>() with(cursor) { while (moveToNext()) { val itemId = getLong(getColumnIndexOrThrow(BaseColumns._ID)) itemIds.add(itemId) } } cursor.close()
Java
List itemIds = new ArrayList<>(); while(cursor.moveToNext()) { long itemId = cursor.getLong( cursor.getColumnIndexOrThrow(FeedEntry._ID)); itemIds.add(itemId); } cursor.close();
Veritabanında bilgileri silme
Tablodan satır silmek için şu koşulları karşılayan seçim ölçütleri sağlamanız gerekir:
satırları delete()
yöntemine tanımlamak için kullanılır. Bu mekanizma, query()
yönteminin seçim bağımsız değişkenleriyle aynı şekilde çalışır. Her bir
seçim yan tümcesine ve seçim bağımsız değişkenlerine dönüştürme. Bu yan tümce, incelenecek sütunları tanımlar ve sütun testlerini birleştirmenize de olanak tanır. Bağımsız değişkenler, yan tümceyle bağlanan ve test edilecek değerlerdir.
Sonuç, normal bir SQL ifadesiyle aynı şekilde işlenmediğinden SQL eklemeye karşı bağışıktır.
Kotlin
// Define 'where' part of query. val selection = "${FeedEntry.COLUMN_NAME_TITLE} LIKE ?" // Specify arguments in placeholder order. val selectionArgs = arrayOf("MyTitle") // Issue SQL statement. val deletedRows = db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs)
Java
// Define 'where' part of query. String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?"; // Specify arguments in placeholder order. String[] selectionArgs = { "MyTitle" }; // Issue SQL statement. int deletedRows = db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs);
delete()
yönteminin döndürdüğü değer, veritabanından silinen satırların sayısını gösterir.
Veritabanı güncelleme
Veritabanı değerlerinizin bir alt kümesini değiştirmeniz gerektiğinde update()
yöntemini kullanın.
Tablo güncellendiğinde insert()
'un ContentValues
söz dizimi, delete()
'ın WHERE
söz dizimine birleştirilir.
Kotlin
val db = dbHelper.writableDatabase // New value for one column val title = "MyNewTitle" val values = ContentValues().apply { put(FeedEntry.COLUMN_NAME_TITLE, title) } // Which row to update, based on the title val selection = "${FeedEntry.COLUMN_NAME_TITLE} LIKE ?" val selectionArgs = arrayOf("MyOldTitle") val count = db.update( FeedEntry.TABLE_NAME, values, selection, selectionArgs)
Java
SQLiteDatabase db = dbHelper.getWritableDatabase(); // New value for one column String title = "MyNewTitle"; ContentValues values = new ContentValues(); values.put(FeedEntry.COLUMN_NAME_TITLE, title); // Which row to update, based on the title String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?"; String[] selectionArgs = { "MyOldTitle" }; int count = db.update( FeedReaderDbHelper.FeedEntry.TABLE_NAME, values, selection, selectionArgs);
update()
yönteminin döndürdüğü değer, veritabanında etkilenen satırların sayısıdır.
Kalıcı veritabanı bağlantısı
Veritabanı kapalıyken getWritableDatabase()
ve getReadableDatabase()
'ı aramak pahalı olduğundan, veritabanı bağlantınızı erişmeniz gerektiği sürece açık bırakmanız gerekir. Genellikle en iyi seçenek, veritabanını kapatmak
bölümünde bulabilirsiniz.onDestroy()
Kotlin
override fun onDestroy() { dbHelper.close() super.onDestroy() }
Java
@Override protected void onDestroy() { dbHelper.close(); super.onDestroy(); }
Veritabanınızda hata ayıklama
Android SDK'da, göz atmanızı sağlayan bir sqlite3
kabuk aracı bulunur
tablo içeriği, SQL komutlarını çalıştırma ve SQLite'ta faydalı diğer işlevleri gerçekleştirme
veri tabanları. Daha fazla bilgi için kabuk komutlarının nasıl yayınlanacağına bakın.