DBFlow新版使用,該實例涉及功能:1.資料庫增刪改查(操作封裝),2.同/非同步+事物操作,3.資料庫升級(新增表+新增欄位+預設值設置等)+自定義資料庫存儲路徑... ...
一、DBFlow4.2.4介紹
DBFlow是一個基於AnnotationProcessing(註解處理器)的ORM框架。此框架設計為了速度、性能和可用性。消除了大量死板的資料庫代碼,取而代之的是強大而又簡介的API介面。
1、無縫支持多個資料庫;
2、使用annotation processing提高速度;
3、ModelContainer類庫可以直接解析像JSON這樣的數據;
4、增加靈活性的豐富介面。
三、該實例涉及功能:
1.資料庫增刪改查(操作封裝)
2.同/非同步+事物操作
在項目目錄的build.gradle中加入:
allprojects { repositories { ... maven { url "https://jitpack.io" } } }
在工程目錄的build.gradle中加入:
apply plugin: 'com.android.application' def dbflow_version = "4.2.4" android { ... } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:27.1.1' testImplementation 'junit:junit:4.12' annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:$dbflow_version" // gradle 3.0.0 可以使用 implementation,否則用 compile implementation "com.github.Raizlabs.DBFlow:dbflow-core:$dbflow_version" implementation "com.github.Raizlabs.DBFlow:dbflow:$dbflow_version" // }
1.創建DataBase
@Database(name = AppDatabase.NAME, version = AppDatabase.VERSION) public class AppDatabase { //版本號 public static final int VERSION = 1; //資料庫名稱 public static final String NAME = "App2018DB"; }
2.
必須繼承BaseModel,BaseModel包含了基本的資料庫操作(save、delete、update、insert、exists)
//必須是共有的修飾符,如果使用私有屬性則返回(老的版本記得寫get/set方法就可以了): // Error:Execution failed for task ':xxx:compileDebugJavaWithJavac'.> //Compilation failed; see the compiler error output for details. @Table(database =AppDatabase.class) public class BigSeaInfo0 extends BaseModel{ @PrimaryKey(autoincrement = true) @Column public int userId; @Column public String name; @Column(defaultValue = "18")//預設值無效 public int age=20;//有效 @Column//(name = "desc") public String remarks; @Column public long money=3000; } //備註:DBFlow會根據你的類名自動生成一個表明,以此為例: //這個類對應的表名為:UserData_Table //常用註解操作符: // @Table、 // @PrimaryKey、//主鍵 // @Column、//列 // @Unique、:唯一的 // @ForeignKey:外鍵,一般數據褲不常用 // 等
3.DbFlow初始化
//初始化方式有三種: public class App extends Application { @Override public void onCreate() { super.onCreate(); //DBFlow初始配置:3中方式 //FlowManager.init(this);// 初始化方式1 //FlowManager.init(new FlowConfig.Builder(this).build());//初始化方式2 //自定義路徑-初始化方式3--> api>=23需授權(文件讀寫),再添加此操作,具體見StartActivity // FileDatabaseContext mSdDatabaseContext = // new FileDatabaseContext(getApplicationContext()); // FlowManager.init(mSdDatabaseContext); FlowLog.setMinimumLoggingLevel(FlowLog.Level.V);//添加日誌 }
4.一般使用操作:
//-------------------------添加操作----------------------- //DBFlow 對數據的增刪改查已經做了封裝,使用起來比較簡單 private void insertBaseModle() { BigSeaInfo0 product = new BigSeaInfo0(); product.name = "P000" + index; product.age = 18 + index; product.remarks = "備註-" + index; product.money = 300 * index; // product.insert(); boolean success = product.save(); index++; // 執行到這裡之後 id 已經被賦值 App.showToast(this, "添加結果:" + success); } //-------------------------修改操作----------------------- /* * 更新和刪除可以為先查詢後操作,只要查到對應的數據,在 bean 上做修改, * 然後調用 update() 方法,資料庫就能修改完成。還有另一中更接近 sql 語法的方式。 */ private void updateBaseModle0() { // 第一種 先查後改 BigSeaInfo0 product = SQLite.select() .from(BigSeaInfo0.class)//查詢第一個 .where(BigSeaInfo0_Table.name.is("P0000")) .querySingle();// 區別與 queryList() if (product != null) { Log.d("zhh_Bd", "Update: " + product.name + " update to P0000"); product.name = "P000X"; boolean success = product.update(); App.showToast(this, "修改結果:" + success); } else { App.showToast(this, "name=P0000的條件數據不存在:"); } } // update:第二種 高級用法,刪改查都是同理 private void updateBaseModle1() { SQLite.update(BigSeaInfo0.class) .set(BigSeaInfo0_Table.name.eq("PXXXX")) .where(BigSeaInfo0_Table.name.is("P0001")) .execute(); } //-------------------------刪除操作----------------------- //刪除1 private void deleteBaseModle() { // 第一種 先查後刪 BigSeaInfo0 product = SQLite.select() .from(BigSeaInfo0.class) .where(BigSeaInfo0_Table.name.is("P00010")) .querySingle();//查詢單個 if (product != null) { product.delete(); Log.d("zhh_db", "Delete: " + product.name); } //刪除一張表 // Delete.table(BigSeaInfo0.class); // 刪除多張表 // Delete.tables(MyTable1.class, MyTable2.class); } //刪除2 private void deleteBaseModle1() { // 第二種 SQLite.delete(BigSeaInfo0.class) .where(BigSeaInfo0_Table.name.is("PXXXX")) .execute(); } //-------------------------查詢操作----------------------- //查詢 private void selectBaseModle() { // List<BigSeaInfo0> list = SQLite.select().from(BigSeaInfo0.class).queryList(); List<BigSeaInfo0> list = SQLite.select().from(BigSeaInfo0.class). where(BigSeaInfo0_Table.name.like("P%")).queryList(); printData(list); } //非同步執行查詢:儘管是非同步的,但是線程安全的 private void selectBaseModleSync() { SQLite.select().from(BigSeaInfo0.class)//.where(BigSeaInfo0_Table.name.is("")) .async().queryListResultCallback(new QueryTransaction. QueryResultListCallback<BigSeaInfo0>() { @Override public void onListQueryResult(QueryTransaction transaction, @NonNull List<BigSeaInfo0> tResult) { printData(tResult);//更新UI } }); } //指定欄位升降序查詢 private void selectBaseModleOrderBy() { //true為'ASC'正序, false為'DESC'反序 List<BigSeaInfo0> list = SQLite.select() .from(BigSeaInfo0.class) .where() .orderBy(BigSeaInfo0_Table.userId, true) .queryList(); printData(list); } //分組查詢--以年齡+名字分組查詢:先排序後分組 private void selectBaseModleGroupBy() { List<BigSeaInfo0> list = SQLite.select() .from(BigSeaInfo0.class) .groupBy(BigSeaInfo0_Table.age, BigSeaInfo0_Table.name) .queryList(); printData(list); } //分頁查詢--每頁查詢3條--》limit後面跟的是3條數據,offset:是從第(page*3)條開始讀取 private void selectPageBaseModle(int page) { List<BigSeaInfo0> list = SQLite.select() .from(BigSeaInfo0.class) .limit(3)//條數-》3 .offset(page * 3)//當前頁數 .queryList(); printData(list); }
5.事物回滾+非同步操作
//-------------------------添加操作----------------------- private void insertBaseModle0() { BigSeaInfo0 product = new BigSeaInfo0(); product.name = "P000" + index; product.age = 18 + index; product.remarks = "備註-" + index; product.money = 300 * index; //boolean success = product.save(); boolean success = product.async().save();//非同步 //添加成功,但是返回為false,因為是非同步,還未執行完成非同步就返回值了,所以需要配置事物操作(個人理解) index++; // 執行到這裡之後 id 已經被賦值 App.showToast(this, "添加結果:" + success); } //非同步執行查詢:儘管是非同步的,但是線程安全的 private void insertBaseModle1() { //自己去實現事務批量保存 Transaction transaction = FlowManager.getDatabase(AppDatabase.class). beginTransactionAsync(new ITransaction() { @Override public void execute(DatabaseWrapper databaseWrapper) { // todo 處理list保存:批量添加 int i = 0; Iterator<BigSeaInfo0> iterator = resultList().iterator(); while (iterator.hasNext()) { BigSeaInfo0 info = iterator.next(); boolean success = info.save(); i = success ? ++i : i; } Log.i("zhh_db_sync", "成功添加了數據條數:" + i); } }).build(); transaction.execute(); //transaction.executeSync();//非同步執行 } private void insertBaseModle2() { FlowManager.getDatabase(AppDatabase.class) .beginTransactionAsync(new ProcessModelTransaction.Builder<>( new ProcessModelTransaction.ProcessModel<BigSeaInfo0>() { @Override public void processModel(BigSeaInfo0 bigSeaInfo0, DatabaseWrapper wrapper) { // do work here -- i.e. user.delete() or user.update() //增刪改操作等,這裡添加集合對象 boolean success = bigSeaInfo0.save(); Log.i("zhh_db_sync", "添加結果" + success); } }).addAll(resultList()).build()) .error(new Transaction.Error() { @Override public void onError(Transaction transaction, Throwable error) { App.showToast(DbFlowTransactionActivity.this, "error結果:" + error.getMessage()); Log.i("zhh_db_sync", "error結果" + error.getMessage()); } }) .success(new Transaction.Success() { @Override public void onSuccess(Transaction transaction) { App.showToast(DbFlowTransactionActivity.this, "success結果:" + transaction.name()); Log.i("zhh_db_sync", "添加success"); } }).build() // .execute();//同步 .executeSync();//非同步 } //-------------------------修改||刪除操作----------------------- private void updateBaseModle0() { //不存在的條件數據做更改,也走成功的方法 SQLite.update(BigSeaInfo0.class) .set(BigSeaInfo0_Table.name.eq("PXXXX")) .where(BigSeaInfo0_Table.name.is("P0001")) .async() .error(new Transaction.Error() { @Override public void onError(@NonNull Transaction transaction, @NonNull Throwable error) { Log.i("zhh_db_sync", "非同步修改error---" + error.getMessage()); } }).success(new Transaction.Success() { @Override public void onSuccess(@NonNull Transaction transaction) { Log.i("zhh_db_sync", "非同步修改success"); } }).execute(); } //刪除同上,SQLite.update--》改為SQLite.delete //-------------------------查詢操作----------------------- //提供了三種方式 //方式1:QueryResultSingleCallback:單個查詢 SQLite.select().from(BigSeaInfo0.class).where(BigSeaInfo0_Table.name.is("P0000")) .async()//非同步查詢 .querySingleResultCallback(new QueryTransaction. QueryResultSingleCallback<BigSeaInfo0>() { @Override public void onSingleQueryResult(QueryTransaction transaction, @Nullable BigSeaInfo0 bigSeaInfo0) { if(null!=bigSeaInfo0){ Log.i("zhh_db_sync", "對象查詢-----非同步2--id---" + bigSeaInfo0.userId + ",name->" + bigSeaInfo0.name + ",age---" + bigSeaInfo0.age + ",note--" + bigSeaInfo0.remarks + ",money-->" + bigSeaInfo0.money); }else{ App.showToast(DbFlowTransactionActivity.this,"數據為空"); } } }) .error(new Transaction.Error() { @Override public void onError(@NonNull Transaction transaction, @NonNull Throwable error) { Log.i("zhh_db_sync", "Sync-----error--" + error.getMessage()); } }).success(new Transaction.Success() { @Override public void onSuccess(@NonNull Transaction transaction) { Log.i("zhh_db_sync", "Sync-----success--" + transaction.name()); //更新Ui操作 } }).execute(); //方式2:QueryResultListCallback:集合查詢 SQLite.select().from(BigSeaInfo0.class)//.where(BigSeaInfo0_Table.name.is("")) .async()//非同步查詢 .queryListResultCallback(new QueryTransaction. QueryResultListCallback<BigSeaInfo0>() { @Override public void onListQueryResult(QueryTransaction transaction, @NonNull List<BigSeaInfo0> tResult) { printData(tResult);//更新UI } }).error(new Transaction.Error() { @Override public void onError(@NonNull Transaction transaction, @NonNull Throwable error) { Log.i("zhh_db_sync", "SyncList--error---" + error.getMessage()); } }).success(new Transaction.Success() { @Override public void onSuccess(@NonNull Transaction transaction) { Log.i("zhh_db_sync", "SyncList---success--" ); } }).execute(); //方式3:QueryResultCallback:方式1+2的統一 SQLite.select().from(BigSeaInfo0.class).async().queryResultCallback( new QueryTransaction.QueryResultCallback<BigSeaInfo0>() { @Override public void onQueryResult(@NonNull QueryTransaction<BigSeaInfo0> transaction, @NonNull CursorResult<BigSeaInfo0> tResult) { BigSeaInfo0 bigSeaInfo0 = tResult.toModel(); //這裡可以是返回集合:tResult.toList() Log.i("zhh_db_sync", "對象查詢-----非同步1-->id---" + bigSeaInfo0.userId + ",name->" + bigSeaInfo0.name + ",age---" + bigSeaInfo0.age + ",note--" + bigSeaInfo0.remarks + ",money-->" + bigSeaInfo0.money); tResult.close();//關閉資源 } }).execute();
六、資料庫升級
當你升級資料庫@Database版本,只需要添加一個Migration來配置升級操作,DBFlow 已經有它的幾個現成的實現提供給我們進行使用:
1.AlterTableMigration 用於重命名錶,增加列
2.IndexMigration/IndexPropertyMigration 用於索引創建和刪除
3.UpdateTableMigration 升級資料庫的時候更新數據
資料庫升級--添加列(設置預設值)&新增表----版本改為2,之前是1(個人建議version=10---》參照build.gradle中的versionName:1.0)如下:
//----------------升級-新增表:改版本好即可 //----------------升級-新增列:新增下麵代碼 @Migration(version = VERSION, database = AppDatabase.class)//=2的升級 public static class Migration1 extends AlterTableMigration<BigSeaInfo0> { // Migration可設置優先順序,高優先順序的將先被執行。 //Migration有3個方法: //onPreMigrate() 首先被調用,在這兒設置和構造 //migrate() 具體的遷移在這兒執行 //onPostMigrate() 執行一些清理工作,或者執行完成的通知 public Migration1(Class<BigSeaInfo0> table) { super(table); } @Override public void onPreMigrate() { //所有Java標準的數據類型(boolean、byte、short、int、long、float、double等)及相應的包裝類, // 以及String,當然我們還預設提供了對java.util.Date、java.sql.Date與Calendar的支持。 // 使用如下:這裡值添加remarks2 //addColumn(SQLiteType.get(long.class.getName()), "money");//基本數據類型 //addColumn(SQLiteType.get(int.class.getName()), "money");//基本數據類型 //addColumn(SQLiteType.get(double.class.getName()), "money");//基本數據類型:浮點數 //addColumn(SQLiteType.get(String.class.getName()), "money");//基本數據類型:浮點數 addColumn(SQLiteType.TEXT, "remarks2"); } }
具體使用,請下載源碼: