Android 數(shù)據(jù)庫知識回顧

加油

一、前言
二、效果預(yù)覽
三、數(shù)據(jù)庫與框架的基礎(chǔ)使用
(1)第一道:原生數(shù)據(jù)庫
(2)第二道:LitePal框架
(3)第三道:GreenDao框架
四、總結(jié)
五、Demo地址
六、內(nèi)容推薦


一、前言

  • 1.菜鳥作者為什么要寫這篇呢?——隨GitHub上Android數(shù)據(jù)庫框架日新月異,我們應(yīng)該如何選擇一個適合我們的數(shù)據(jù)庫。

當(dāng)然一個好的數(shù)據(jù)庫框架不僅可以提高我們的開發(fā)效率外,還可以提高項目的性能。

  • 2.為什么GitHub上有那么多的開源框架?——不言而喻,應(yīng)該是原生的開發(fā)效率與性能上沒有開源來的優(yōu)秀(哈哈 個人觀點)

  • 3.這篇主要寫什么?——主要回顧數(shù)據(jù)庫的用法。對比一些開源數(shù)據(jù)庫的使用方法(最基礎(chǔ)的使用方式)。因性能弄起來比較麻煩,而且相關(guān)博客也很多大家自己百度即可。

二、效果預(yù)覽

隨便給自己寫的一個簡單Demo,看完UI有沒有一種想捏死作者的沖動...

這里只涉及簡單的存儲操作,復(fù)雜的多對多關(guān)系這里沒有。不瞞大家,想深入理解數(shù)據(jù)庫的同學(xué)可以止步了,這里算基礎(chǔ)回顧

?三、數(shù)據(jù)庫與框架的基礎(chǔ)使用

什么是數(shù)據(jù)庫?什么是SQLite?...就解釋到這里。開始上菜了

先說明一下數(shù)據(jù)庫使用基礎(chǔ)步驟我把他們分為:1.創(chuàng)建數(shù)據(jù)庫 2.創(chuàng)建表 3.數(shù)據(jù)庫操作(增刪改查) 4.更新數(shù)據(jù)庫


(1)第一道:原生數(shù)據(jù)庫

1.首先我們需要創(chuàng)建一個屬于自己的數(shù)據(jù)庫管理類來繼承SQLiteOpenHelper數(shù)據(jù)庫幫助類實現(xiàn)數(shù)據(jù)庫的創(chuàng)建與更新。

public class MySQLiteHelper extends SQLiteOpenHelper {
    private static final String TAG = "MySQLiteHelper";
    //數(shù)據(jù)庫建表語句
    public static final String sql = "create table SqliteDemo (id integer primary key autoincrement, name text(4),address text(5))";
    public static final String sql1 = "create table test1 (id integer primary key autoincrement, name text(4),address text(5))";
    public MySQLiteHelper(@Nullable Context context, @Nullable String name,  @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);//創(chuàng)建數(shù)據(jù)庫調(diào)用方法
    }
    /**
     * 第一次創(chuàng)建數(shù)據(jù)庫時調(diào)用 在這方法里面可以進行建表
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i(TAG, "onCreate: " );
        db.execSQL(sql);
    }
    /**
     * 版本更新的時候調(diào)用
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.i(TAG, "onUpgrade: " );
        switch (oldVersion){
            case 1:
                db.execSQL(sql1);
                break;
        }
    }
}
創(chuàng)建一個數(shù)據(jù)庫:名稱Blcs  版本號 1
MySQLiteHelper blcs = new MySQLiteHelper(context, "Blcs", null, 1);

2.基本操作

//(1)打開數(shù)據(jù)庫并進行寫入操作
SQLiteDatabase db= blcs.getWritableDatabase();

注:Android提供了兩種操作方式:1.執(zhí)行數(shù)據(jù)庫語句 2.調(diào)用封裝好的Api方法

增:插入一條語句

//方式一:
String insert = new StringBuilder()
                    .append("insert into SqliteDemo (name,address) values ('")
                    .append(name).append("','").append(address).append("')")
                    .toString();

//或是
//String insert = "insert into SqlteDemo (name,address) values ('"+name+"','"+address+"')";
db.execSQL(insert);

//方式二:
ContentValues contentValues = new ContentValues();
            contentValues.put("name", name);
            contentValues.put("address", address);
            db.insert("SqliteDemo", null, contentValues);

刪:刪除一條語句

//方式一
String delete = new StringBuilder().append("delete from SqliteDemo where name = '").append(Name).append("' or address = '").append(Address).append("'").toString();

db.execSQL(delete);

//方式二
db.delete("SqliteDemo", "name = ? or address = ?", new String[]{Name, Address});

改:修改一條語句

//根據(jù)指定ID修改name 與 address
//方式一
String update = new StringBuilder().append("update SqliteDemo set name = '").append(Name)
                    .append("' , address = '").append(Address)
                    .append("' where id = ").append(Id)
                    .toString();
db.execSQL(update);
//方式二
ContentValues contentValues = new ContentValues();
            contentValues.put("name", Name);
            contentValues.put("address", Address);
db.update("SqliteDemo", contentValues, "id = ?", new String[]{String.valueOf(Id)});

查:查詢語句

//方式一
//查詢整張表
String query = "select * from SqliteDemo";
//獲取表中存在這個地址的數(shù)據(jù)
String query = new StringBuilder().append("select * from SqliteDemo where address = '")
                    .append(Address).append("'").toString();
//獲取表中存在這個地址和姓名的數(shù)據(jù)
String query = new StringBuilder().append("select * from SqliteDemo where name = '")
                    .append(Name).append("' and address = '").append(Address).append("'").toString();

//執(zhí)行數(shù)據(jù)庫語句
Cursor cursor = db.rawQuery(query, null);

//方式二
//查詢整張表
String selection = null;
String str = null;
//獲取表中存在這個地址的數(shù)據(jù)
String selection = "address = ?";
String str = new String[]{Address};
//獲取表中存在這個地址和姓名的數(shù)據(jù)
String selection = "name = ? and address = ?";
String str = new String[]{Name, Address};
//執(zhí)行相應(yīng)的Api
Cursor cursor = db.query("SqliteDemo", null, selection, str, null, null, null);

還沒結(jié)束 ,當(dāng)我們拿到Cursor對象后還要進行最后的數(shù)據(jù)獲取

ArrayList<SqliteDemo> dats = new ArrayList<>();

while (cursor.moveToNext()) {
            SqliteDemo sqliteDemo = new SqliteDemo();
            long id = cursor.getLong(cursor.getColumnIndex("id"));
            String name = cursor.getString(cursor.getColumnIndex("name"));
            String address = cursor.getString(cursor.getColumnIndex("address"));
            sqliteDemo.setId(id);
            sqliteDemo.setName(name);
            sqliteDemo.setAddress(address);
            dats.add(sqliteDemo);
        }
return dats;

3.數(shù)據(jù)庫更新

當(dāng)我們數(shù)據(jù)庫有變化,并且要發(fā)布新版本的時候別忘了升級一下數(shù)據(jù)庫版本號。并且還需要在MySQLiteHelper 的 onUpgrade方法中進行處理。

(2)第二道:LitePal框架

簡單描述:這是郭神早期對原生數(shù)據(jù)庫封裝的一個數(shù)據(jù)庫框架

優(yōu)點嘛:......用了就知道了哈

GitHub:https://github.com/LitePalFramework/LitePal

guolin:https://blog.csdn.net/sinyu890807/column/info/android-database-pro

1.基本配置

1.添加依賴
dependencies {
    implementation 'org.litepal.android:java:3.0.0'
}
or
dependencies {
    implementation 'org.litepal.android:kotlin:3.0.0'
}

2,創(chuàng)建數(shù)據(jù)庫:在assets 添加litepal.xml //還有另外一種創(chuàng)建數(shù)據(jù)庫的方式 具體可以到GitHub或博客上了解

<?xml version="1.0" encoding="utf-8"?>
<litepal>
      //數(shù)據(jù)庫昵稱
    <dbname value="Blcs1" />
    //版本號
    <version value="1" />
    //數(shù)據(jù)庫表
    <list>
        <mapping class="blcs.lwb.utils.bean.SqliteDemo" />
    </list>

</litepal>

3.初始化 AndroidManifest.xml

<manifest>
    <application
        android:name="com.example.MyOwnApplication"
        ...
    >
        ...
    </application>
</manifest>

public class MyOwnApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        LitePal.initialize(this);
    }
    ...
}

4.數(shù)據(jù)庫的操作

這里對象需要繼承LitePalSupport,調(diào)用里面的api執(zhí)行相應(yīng)的數(shù)據(jù)庫處理,可以給屬性相應(yīng)的注解,相對簡單,這里就不貼了。一切從簡

public class SqliteDemo extends LitePalSupport {
    private Long id;
    private String name;
    private String address;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

//創(chuàng)建要保存的對象,調(diào)用save方法直接保存  因為繼承了LitePalSupport 里面提供了許多保存的APi ,可以根據(jù)需求選擇合適的方法
SqliteDemo sqliteDemo = new SqliteDemo();
            sqliteDemo.setName(name);
            sqliteDemo.setAddress(address);
            sqliteDemo.save();
//例:異步保存:開個線程進行保存,處理完監(jiān)聽回調(diào)是否保存成功
sqliteDemo.saveAsync().listen(new SaveCallback() {
                @Override
                public void onFinish(boolean success) {
                    List<SqliteDemo> all = LitePal.findAll(SqliteDemo.class);
                    mAdapter.setNewData(all);
                }
            });

//LitePal.delete();
//LitePal.deleteAll();
//LitePal.deleteAsync()
LitePal.deleteAllAsync(SqliteDemo.class,"name = ? or address = ?",Name,Address).listen(new UpdateOrDeleteCallback() {
                    @Override
                    public void onFinish(int rowsAffected) {
                        List<SqliteDemo> all = LitePal.findAll(SqliteDemo.class);
                        mAdapter.setNewData(all);
                    }
                });

//LitePal.update();
//LitePal.updateAll();
//LitePal.updateAsync();
//LitePal.updateAllAsync();
 ContentValues contentValues = new ContentValues();
            contentValues.put("name", Name);
            contentValues.put("address", Address);
            LitePal.updateAsync(SqliteDemo.class,contentValues,Id).listen(new UpdateOrDeleteCallback() {
                @Override
                public void onFinish(int rowsAffected) {
                    List<SqliteDemo> all = LitePal.findAll(SqliteDemo.class);
                    mAdapter.setNewData(all);
                }
            });

//查詢?nèi)?
List<SqliteDemo> all = LitePal.findAll(SqliteDemo.class);

//獲取名字和地址對應(yīng)的數(shù)據(jù)
String selection = "name = ? and address = ?";
List<SqliteDemo> all = LitePal.where(selection, Name, Address).find(SqliteDemo.class);

//查詢里面隱藏著許多有用的Api,有興趣的同學(xué)可以繼續(xù)深究.這里不解釋。否則導(dǎo)致篇幅太長

5.數(shù)據(jù)庫的更新

使用這個框架最大的優(yōu)點是,我們已經(jīng)不需要自己去寫數(shù)據(jù)庫的更新方法了。只需要提高一下版本號即可,剩下的框架已經(jīng)都幫我們處理好了。

6.混淆

-keep class org.litepal.** {
    *;
}
-keep class * extends org.litepal.crud.DataSupport {
    *;
}

-keep class * extends org.litepal.crud.LitePalSupport {
    *;
}

(3)第三道:GreenDao框架

greendao :https://github.com/greenrobot/greenDAO

介紹:http://greenrobot.org/greendao/documentation/

參考博客:http://www.lxweimin.com/p/53083f782ea2

簡單描述:目前GitHub上最熱門的數(shù)據(jù)庫框架之一,相對其他數(shù)據(jù)庫框架star也是最多的一個。

1.基本配置

// In your root build.gradle file:
buildscript {
    repositories {
        jcenter()
        mavenCentral() // add repository
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.1'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
    }
}
// In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin

dependencies {
    implementation 'org.greenrobot:greendao:3.2.2' // add library
}

混淆

-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
-dontwarn org.greenrobot.greendao.database.**
-dontwarn rx.**
### greenDAO 2
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties

配置數(shù)據(jù)庫信息:

    greendao {
        schemaVersion 1 //數(shù)據(jù)庫版本號
        // 設(shè)置DaoMaster、DaoSession、Dao 包名
        daoPackage 'blcs.lwb.utils.greendao'
        targetGenDir 'src/main/java'
    }

2.創(chuàng)建持久化對象

主要:給持久化對象添加@Entity 注解 ,然后Build -- Make Project 重新編譯一下 會自動生成DaoMaster、DaoSession、GreenDaoDao

@Entity
public class GreenDao {
    @Id
    private Long id;
    private String name;
    private String address;
    @Generated(hash = 534050545)
    public GreenDao(Long id, String name, String address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }
    @Generated(hash = 766040118)
    public GreenDao() {
    }
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return this.address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}

3.創(chuàng)建數(shù)據(jù)庫

public class MyApplication extends BaseApplication {
     @Override
    public void onCreate() {
        super.onCreate();
        //GreenDao
        initGreenDao();
    }

    private void initGreenDao() {
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "Blcs2.db");
        SQLiteDatabase db = helper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
    }
    private static DaoSession daoSession;
    public static DaoSession getDaoSession() {
        return daoSession;
    }
}

4.基本操作

//獲取GreenDao數(shù)據(jù)庫操作對象
 DaoSession daoSession = MyApplication.getDaoSession();
//獲取指定的操作對象
GreenDaoDao greenDaoDao = daoSession.getGreenDaoDao();

  GreenDao demo = new GreenDao();
            demo.setName(name);
            demo.setAddress(address);
            daoSession.insert(demo);
//或
            greenDaoDao.insert(demo);

//查出需要刪除的對象 ,然后進行刪除
daoSession.delete(bean);
//或
greenDaoDao.delete(bean);

//根據(jù)ID查找某個對象進行更改
List<GreenDao> demos = daoSession.queryRaw(GreenDao.class, "where _id = ?", "" + Id);
            GreenDao demo = demos.get(0);
            demo.setName(Name);
            demo.setAddress(Address);
            daoSession.update(demo);
//或
            greenDaoDao.update(demo);

//查詢?nèi)?List<GreenDao> greenDaoBeans = daoSession.loadAll(GreenDao.class);
//根據(jù)條件查詢
List<GreenDao> greenDaoBeans = daoSession.queryRaw(GreenDao.class, "where NAME = ? and ADDRESS = ?", Name,Address);

大部分daoSession操作方法 ,greenDaoDao也會有

4.數(shù)據(jù)庫更新

GreenDao的OpenHelper下有個 onUpgrade(Database db, int oldVersion, int newVersion)方法,當(dāng)設(shè)置的數(shù)據(jù)庫版本改變時,在數(shù)據(jù)庫初始化的時候就會回調(diào)到這個方法,我們可以通過繼承OpenHelper重寫onUpgrade方法來實現(xiàn)數(shù)據(jù)庫更新操作。

注:如果沒有重寫更新方法只升級版本號的話:會導(dǎo)致數(shù)據(jù)丟失。


四、總結(jié)

使用原生數(shù)據(jù)庫容易出現(xiàn)語句錯誤,使用繁瑣,提供的Api也比較少。相對于原生數(shù)據(jù)庫,我們可以采用郭神的LitePal框架,主要是基于原生數(shù)據(jù)庫封裝的。提供的Api比較豐富,而且使用也方便。

但是從性能方面上來看可能沒有GreenDdao框架高,具體可以查看GreenDdao文檔。里面有進行詳細(xì)的描述。

當(dāng)然還有許多不錯的數(shù)據(jù)框架:DBFlowActiveAndroidORMLiteRealmAfinal ....

最后在推薦一個性能更好的數(shù)據(jù)庫框架objectbox

官網(wǎng):https://objectbox.io/

GitHub:https://github.com/objectbox/objectbox-java

為什么菜鳥作者不寫呢?——還在學(xué)習(xí)中..


注:AS中并不能直接打開.db文件 所以一般要查看數(shù)據(jù)庫文件需要借助工具

不過那樣會很麻煩,需要先找到文件導(dǎo)出后再工具中查看。

所以這里可以引用Android-Debug-Database,在不借助工具的情況下查看數(shù)據(jù)庫。

五、Demo地址

Github:https://github.com/DayorNight/BLCS

碼云:https://gitee.com/blcs/BLCS

apk下載體驗地址:https://www.pgyer.com/BLCS

六、內(nèi)容推薦

CSDN: 《Android 數(shù)據(jù)庫知識回顧》
《Android 下載安裝應(yīng)用APK封裝(適配8.0)》
《Android Notification通知簡單封裝(適配8.0)???????》???????
《Android 仿RxDialog自定義DialogFragment》
《Android 獲取App應(yīng)用、緩存、數(shù)據(jù)等大小適配8.0(仿微信存儲空間)》

如果你覺得寫的不錯或者對您有所幫助的話

不妨頂一個【微笑】,別忘了點贊、收藏、加關(guān)注哈

看在花了這么多時間整理寫成文章分享給大家的份上,記得手下留情哈

您的每個舉動都是對我莫大的支持

?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容