Android最好用的數(shù)據(jù)庫框架——DBFLOW全面解析

前言

為什么說DBFLOW是最好用的數(shù)據(jù)庫框架?因為它綜合了各個數(shù)據(jù)庫的框架的優(yōu)點,它比GreenDao要使用簡單,同時又比ActiveAndroid性能高很多,它是一款操作簡單又高效的ORM框架。

初始DBFLOW

官方介紹

根據(jù)官方介紹可以知道,DBFLOW是一個為Android設(shè)計的簡單高效的數(shù)據(jù)庫類庫,它基于注解在編程過程中生成操作類,性能高效,操作安全。

DBFLOW正確使用姿勢

DBFLOW配置(build.gradle版本3.0以下)

引入apt和maven,配置在工程下gradle里面

  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.0.0-beta6'
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

allprojects {
  repositories {
    jcenter()
    maven { url "https://jitpack.io" }
  }

在app的gradle下配置apply plugin: 'com.neenbedankt.android-apt',同時導入依賴包

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
def dbflow_version = "3.0.0-beta4"
android {
  compileSdkVersion 23
  buildToolsVersion "23.0.2"

  defaultConfig {
    applicationId "cn.taoweiji.dbflowexample"
    minSdkVersion 14
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
  }
  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  apt "com.github.Raizlabs.DBFlow:dbflow-processor:${dbflow_version}"
  compile "com.github.Raizlabs.DBFlow:dbflow-core:${dbflow_version}"
  compile "com.github.Raizlabs.DBFlow:dbflow:${dbflow_version}"
}

以上就是build.gradle版本3.0以下的DBFLOW的配置方式,基本上就是各種導包
--------------------------------------分割線-----------------------------------------
在Android Studio3.0以上版本、build.gradle版本3.0以上,已經(jīng)把apt的注解方式修改為annotationProcessor,對應(yīng)在配置也發(fā)生了變化,不需要再配置apt相關(guān)的設(shè)置
build.gradle版本3.0以上DBFLOW相關(guān)配置
工程下的gradle文件

buildscript {
    
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.0'
//        不需要配置apt
//        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven { url "https://www.jitpack.io" }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

app下的gradle文件

apply plugin: 'com.android.application'
def dbflow_version = "4.2.1"
android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.kaka.dbflowdemo"
        minSdkVersion 18
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:${dbflow_version}"
    implementation "com.github.Raizlabs.DBFlow:dbflow-core:${dbflow_version}"
    implementation "com.github.Raizlabs.DBFlow:dbflow:${dbflow_version}"
    // sql-cipher database encyrption (optional)
    implementation "com.github.Raizlabs.DBFlow:dbflow-sqlcipher:${dbflow_version}"

}

建議使用annotationProcessor這種注解方法,不僅是配置簡單,而且Android Studio對這種注解方式也進行了優(yōu)化。

初始化DBFLOW

public class MyApp extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        //初始化DBFLOW
        FlowManager.init(this);
    }
}

別忘了在清單文件里面把application修改為當前Application

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

@Database(name = AppDataBase.NAME,version = AppDataBase.VERSION)
public class AppDataBase {
    public static final String NAME="AppDataBase";
    public static final int VERSION=1;
}

創(chuàng)建一個類,需要聲明一下數(shù)據(jù)庫的NAME和VERSION,該@Database注釋生成一個DatabaseDefinition現(xiàn)在引用名為“AppDatabase.db”的文件中的磁盤上的SQLite數(shù)據(jù)庫。你可以在代碼中引用它,DatabaseDefinition db = FlowManager.getDatabase(AppDatabase.class);

創(chuàng)建表

兩種方式

第一種(不推薦)

@Table(database = AppDataBase.class)
public class User {
    @PrimaryKey
    UUID id;

    @Column
    String name;

    @Column
    int age;
}

這種是最簡單的方式,創(chuàng)建User類,通過注解來聲明對應(yīng)的數(shù)據(jù)庫字段,@PrimaryKey是主鍵,@Column是字段的意思
第二種(推薦)

@Table(database = AppDataBase.class)
public class User2Model extends BaseModel {

    @PrimaryKey(autoincrement = true)
    private int id;

    @Column
    private String name;

    @Column
    private int age;

    @Column
    private long timeStamp;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public long getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(long timeStamp) {
        this.timeStamp = timeStamp;
    }
}

使用這種方法創(chuàng)建表我們推薦,繼承了BaseModel以后會更好更方便地讓我們操作數(shù)據(jù),代碼更加簡潔。
注:不要重寫構(gòu)造方法,不要重寫構(gòu)造方法,不要重寫構(gòu)造方法;重要的事情說三遍。

CRUD基本操作

第一種創(chuàng)建表的方式的操作

        User user=new User();
        user.id= UUID.randomUUID();
        user.name="kaka";
        user.age=18;
        ModelAdapter<User> adapter=FlowManager.getModelAdapter(User.class);
        //插入User
        adapter.insert(user);
        //修改名字
        user.name = "Test";
        adapter.update(user);
        User userQuery=SQLite.select().from(User.class).querySingle();
        Log.e(TAG,"id="+userQuery.id+",name="+userQuery.name+",age="+userQuery.age);

第二種創(chuàng)建表的方式

        User2Model userModel=new User2Model();
        userModel.setName("UserModel");
        userModel.setAge(new Random().nextInt(100));
        userModel.save();
        userModel.update();
        userModel.delete();

從代碼也可以看出第二種方式的代碼更加簡潔,打開BaseModel源碼看一眼里面重寫了getModelAdapter方法

public ModelAdapter getModelAdapter() {
        if (modelAdapter == null) {
            modelAdapter = FlowManager.getModelAdapter(getClass());
        }
        return modelAdapter;
    }

跟第一種實現(xiàn)的方式ModelAdapter<User> adapter=FlowManager.getModelAdapter(User.class);其實是一樣的,只不過更簡單一些。
查詢:
DBFLOW在查詢方法提高了很強大的支持,無論你是要排列、分組還是各種條件查詢都可以滿足

 List<User2Model> user2Models=SQLite.select().from(User2Model.class).where(User2Model_Table.age.greaterThan(18),User2Model_Table.name.eq("UserModel"))
                .orderBy(OrderBy.fromNameAlias(NameAlias.of("id")))
                .groupBy(NameAlias.of("id"))
                .queryList();
        if (user2Models.size()!=0){
            for (User2Model user2Model:user2Models){
                Log.e(TAG,"id="+user2Model.getId()+",name="+user2Model.getName()+",age="+user2Model.getAge());
            }
        }else{
            Toast.makeText(this,"數(shù)據(jù)為0",Toast.LENGTH_SHORT).show();
        }

看到這樣小伙伴們可能要問了User2Model_Table這個是個什么鬼,之前在對DBFLOW介紹的時候也說到了,DBFLOW是根據(jù)注解在編譯過程生成對應(yīng)的操作類,在你建好表(User2Model)以后,Make Project一下(或者ReBuild只要讓代碼重新編譯一下)就會生成對應(yīng)User2Model_Table操作類對象,這個XXX_Table操作對象在條件搜索過程都會被用到。

事務(wù)操作、批量操作

事務(wù)操作是我們數(shù)據(jù)庫不得不去了結(jié),DBFLOW當然也支持了事務(wù)的相關(guān)操作。

 FlowManager.getDatabase(AppDataBase.class).executeTransaction(new ITransaction() {
            @Override
            public void execute(DatabaseWrapper databaseWrapper) {
                for (int i=0;i<100;i++){
                    User2Model userModel=new User2Model();
                    userModel.setName("UserModel");
                    userModel.setAge(new Random().nextInt(100));
                    userModel.save(databaseWrapper);
                }
            }
        });

這種是同步事務(wù)的方法,雖然DBFLOW執(zhí)行的速度非??欤室埠芎?,但是我們不推薦,因為當我們批量操作數(shù)據(jù)越來越大的時候,同步事務(wù)就會變成一個耗時的操作,而耗時操作我們要放在子線程里執(zhí)行,這樣就需要異步執(zhí)行事務(wù)的方法

//異步事務(wù)
        FlowManager.getDatabase(AppDataBase.class).beginTransactionAsync(new ITransaction() {
            @Override
            public void execute(DatabaseWrapper databaseWrapper) {
                for (int i=0;i<100;i++){
                    User2Model userModel=new User2Model();
                    userModel.setName("UserModel");
                    userModel.setAge(new Random().nextInt(100));
                    userModel.save(databaseWrapper);
                }
            }
        }).success(new Transaction.Success() {
            @Override
            public void onSuccess(@NonNull Transaction transaction) {
                Log.e(TAG,"onSuccess()");
            }
        }).error(new Transaction.Error() {
            @Override
            public void onError(@NonNull Transaction transaction, @NonNull Throwable error) {
                Log.e(TAG,"onError()");
            }
        }).build().execute();

一波非常簡潔的鏈式操作,并且提供好了事務(wù)操作成功和失敗的回調(diào)

數(shù)據(jù)庫升級(增加表、修改表字段等)

如果要增加表,除了要創(chuàng)建表以外,還要修改數(shù)據(jù)庫版本號,如果沒有修改數(shù)據(jù)庫版本號,那么再調(diào)表對象的時候就會報出一個經(jīng)典錯誤,no such table,但凡報這個錯誤都是你數(shù)據(jù)版本號沒有修改。
如果要修改表的字段或者增加字段,相對來說稍微麻煩一點。DBFLOW專門提供了AlterTableMigration<T>這個類來修改表相關(guān)的資料。以User2Model這個表為例,假如說我們要增加一個字段timeStamp是long類型的,不僅改數(shù)據(jù)庫版本號,同時在類對象中增加 @Column
private long timeStamp; 字段以外,還需要增加咱們剛才提到的AlterTableMigration的子類來修改

@Migration(version = AppDataBase.VERSION,database = AppDataBase.class)
public class Migration1 extends AlterTableMigration<User2Model> {
    public Migration1(Class<User2Model> table) {
        super(table);
    }

    @Override
    public void onPreMigrate() {
        super.onPreMigrate();
        addColumn(SQLiteType.INTEGER,User2Model_Table.timeStamp.getNameAlias().name());
    }
}

繼承AlterTableMigration重寫onPreMigrate,在里面寫你需要
修改表的操作,這里我們需要增加一個字段addColumn(SQLiteType.INTEGER,User2Model_Table.timeStamp.getNameAlias().name()); 這樣就ok了

總結(jié)

DBFLOW是一個很強大的ORM框架,不僅有文中提到這些基本操作,它還支持Kotlin語言、RxJava以及各種高級用法,不過這些一般在我們客戶端使用的情況不多,這里不作為重點介紹,感興趣的小伙伴可以看一下官網(wǎng)的介紹https://agrosner.gitbooks.io/dbflow/content/StoringData.html

最后的最后放上我的github地址:https://github.com/kaka10xiaobang/DBFLOW_DEMO

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評論 19 139
  • 在年輕的時候,選擇一次跨國長途旅行,讓自己在旅途中觀看世界,認識自我,明白自己到底需要什么,這一年就叫做“間隔年”...
    大象熊貓閱讀 252評論 2 1
  • 喜歡一個人的感覺是什么樣的?或許從沒有什么固定守恒的標準答案:只是因為你是你,不是別人;只是因為有聊不完的共同話題...
    糾纏的離騷閱讀 542評論 0 3
  • 軒轅烈3軒轅烈和軒轅靈兒,兩人青梅走馬一起長大。軒轅霸也很寵愛軒轅靈兒。但他卻不想放過軒轅鴻 “靈兒,起來,不要去...
    老祝讀書閱讀 390評論 3 2
  • 在我們這個快速發(fā)展的時代,我相信大家對于心理學也不陌生,在我們身邊有各種形形色色的書《心理學教你成功之道》,《教...
    夏木波比閱讀 1,105評論 5 10

友情鏈接更多精彩內(nèi)容