SQLite kullanarak veri tasarrufu sağlayın

Verilerin bir veritabanına kaydedilmesi, yinelenen veya yapılandırılmış veriler için idealdir. iletişim bilgileri gibi. Bu sayfada, Arkadaş Bitkiler projesinin veritabanlarına aşina olmanızı sağlar. Bu sayede, veritabanını kullanmaya Android'de SQLite veritabanları. Veritabanı kullanmak için ihtiyaç duyacağınız API'ler android.database.sqlite paketinde sunulmaktadır.

Dikkat: Bu API'ler güçlü olsa da oldukça düşük seviyededir. kullanmak için çok fazla zaman ve çaba gerektirir:

  • Ham SQL sorguları için derleme zamanı doğrulaması yoktur. Verileriniz olarak grafik değişikliklerinden sonra etkilenen SQL sorgularını manuel olarak güncellemeniz gerekir. Bu bu süreç 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, SQL'e yansıtılır deyimleri yerine getirmektir. 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şmeli sınıfları düzenlemenin iyi bir yolu, genel düzeyinde değiştirebilirsiniz. Sonra iç içe bir sınıfını kullanır. Her iç sınıf, ilgili tablonun sütunlarını numaralandırır.

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 işlem, veritabanınıza yardımcı olabilir uyumlu bir şekilde çalışmasını sağlayabilir.

Ö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 İşte size bazı tipik bir tabloyu oluşturan ve silen deyimler:

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. Verileriniz: çünkü bu alan varsayılan olarak diğer uygulamalar veya kullanıcı tarafından erişilebilir.

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 özelliğini kullanmak için şu özelliklere sahip bir alt sınıf oluşturun: onCreate() ve onUpgrade() geri arama yöntemi. anahtar/değer çiftini de onDowngrade() veya onOpen() yöntem, ancak 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

ContentValues ileterek veritabanına veri ekleyin insert() yöntemine itiraz edin:

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, çerçeveye ContentValues boş (yani, put için geçerli değerler) seçin. Bir sütunun adını belirtirseniz çerçeve bir satır ekler ve değerini null olarak ayarlayın. null belirtirseniz, bu örnekte olduğu gibi kod örneği kullanıldığında çerçeve, değer olmadığında satır eklemez.

insert() yöntemleri, satır içine alır veya veriler eklenirken bir hata oluştuysa -1 değerini döndürür. Bu durum, şunlarla sonuçlanabilir: .

Veritabanındaki bilgileri okuma

Bir veritabanından okuma yapmak için query() yöntemini kullanarak seçim ölçütlerinizi ve istediğiniz sütunları iletin. Yöntem, insert() öğelerini birleştirir ve sütun listesi hariç update() eklenecek verileri değil, 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. Bağımsız değişkenler seçimden ayrı olarak sağlandığı için bu tür sorgular birleştirilmeden önce atlanır. Bu işlem, seçim ifadelerinizi SQL'den bağımsız hale getirir yerleştirme. 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ç şu saatte başladığından: konum -1, moveToNext() çağrıldığında "okuma konumu" yerleştirilir uygulamasında sonuçlardaki ilk giriş ve imlecin bu girişteki son girişten sonra olup olmadığını döndürür karar vermemiz gerekecek. Her satır için Cursor, getString() veya getLong() gibi yöntemleri alır. Her bir get yöntemi için istediğiniz sütunun dizin konumunu iletmeniz gerekir. Bunu getColumnIndex() veya getColumnIndexOrThrow(). Tamamlandığında sonuçlar yineleniyor, imleçte close() işlevini çağırın serbest bırakılmasını isteyebilirsiniz. Örneğin, aşağıda bir imleçte depolanan tüm öğe kimliklerinin nasıl alınacağı gösterilmektedir ve bir listeye ekleyin:

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ındaki bilgileri silme

Bir 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. İlgili içeriği oluşturmak için kullanılan işlevi, tablodaki seçim bağımsız değişkenleriyle aynı şekilde query() yöntemini çağırın. Her bir seçim yan tümcesine ve seçim bağımsız değişkenlerine dönüştürme. İlgili içeriği oluşturmak için kullanılan yan tümcesi incelenecek sütunları tanımlar ve aynı zamanda sütunları testler. Bağımsız değişkenler, maddeye bağlı olan ve test edilecek değerlerdir. Sonuç, normal bir SQL deyimiyle aynı şekilde işlenmediğinden, SQL yerleştirme işleminden bağımsızdı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ürülen değeri veritabanından silinen satır sayısını gösterir.

Veritabanı güncelleme

Veritabanı değerlerinizin bir alt kümesini değiştirmeniz gerektiğinde update() yöntemini çağırın.

Tabloyu güncellemek için ContentValues WHERE söz dizimiyle insert() / delete().

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ürülen değeri Veritabanında etkilenen satır sayısı.

Veritabanı bağlantısı devam ediyor

getWritableDatabase() tarihinden beri ve getReadableDatabase() çağrısı yapmak pahalıya mal olacaktır. Bu durumda, veritabanı bağlantınızı Erişebileceğiniz süre boyunca açabilirsiniz. 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.