轉 Android Room數據庫使用


Room使用介紹
1.創建Database
Database包含數據庫的持有者。
作為一個數據庫的管理類,必須用注解 @Database 標注,並且滿足以下條件:

必須是一個抽象類,並且繼承 RoomDatabase。
在 Database 的注解內,必須包含一個或者多個和數據庫關聯的實體類。
包含一個或多個有0個參數的抽象方法,這些方法返回與之關聯實體的Dao對象。
2.創建Entity
代表數據庫關聯的一個表

3.創建Dao
包含可以訪問數據的方法。

Room使用具體分解:
步驟1、創建數據庫database有兩種方式
方式一:Room.inMemoryDatabaseBuilder

//創建一個內存數據庫
//但是這種數據庫的數據只存在於內存中,也就是進程被殺之后,數據隨之丟失
Room.inMemoryDatabaseBuilder(AppGlobals.getApplication(), CacheDatabase.class);
方式二:Room.databaseBuilder,通常使用這種方式創建數據庫

Room.databaseBuilder(AppGlobals.getApplication(), CacheDatabase.class, "ppjoke_cache")
//是否允許在主線程進行查詢
.allowMainThreadQueries()
//數據庫創建和打開后的回調
//.addCallback()
//設置查詢的線程池
//.setQueryExecutor()
//.openHelperFactory()
//room的日志模式
//.setJournalMode()
//數據庫升級異常之后的回滾
//.fallbackToDestructiveMigration()
//數據庫升級異常后根據指定版本進行回滾
//.fallbackToDestructiveMigrationFrom()
// .addMigrations(CacheDatabase.sMigration)
.build();
創建好數據庫后需要添加注解:

@Database(entities = {Cache.class}, version = 1, exportSchema = true)
extities:是數據庫中有哪些表,映射為java中的JavaBean對象,如果有更多的表,則在后面繼續拼接更多的JavaBean即可;
version:是后續數據庫的升級時,比較這個字段
exportSchema:這個字段默認為true,它會導出一個json文件,包含了數據庫在升級或者操作數據表時候的所有的操作,也包含了所有表中的字段,以及字段的描述生成到項目的目錄下,這里需要配置下,以便告訴程序生成文件的路徑:
javaCompileOptions{
annotationProcessorOptions{
arguments=["room.schemaLocation":"$projectDir/schemas".toString()]
}
}

數據庫遷移:

創建一個migration對象:

static Migration sMigration = new Migration(1, 3) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("alter table teacher rename to student");
database.execSQL("alter table teacher add column teacher_age INTEGER NOT NULL default 0");
}
};
將該對象添加到database數據庫中,

Room.databaseBuilder(AppGlobals.getApplication(), CacheDatabase.class, "ppjoke_cache")
.addMigrations(CacheDatabase.sMigration)
.build();
步驟2、創建數表Entity
創建數據表Room為我們提供了很多的注解,所有注解的使用如下:

import java.io.Serializable;

import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;

@Entity(tableName = "cache" //表名
// , indices = {@Index(value = "key", unique = false)}//本表索引,用於大量數據的查詢優化,unique有時候需要保證數據表的某個或者某些字段只有唯一的記錄,可以通過設置@Index注解的unique屬性實現。以下實例代碼實現了避免有兩條記錄包含一樣的key值。
// , inheritSuperIndices = false//如果 該值為true,那么父類中標記的indices{}索引也會算作該表的索引
// , primaryKeys = {"key"}//主鍵,一些策略邏輯會用到,比如插入一條數據時如果已存在,則更新否則算新的插入,那么怎么判斷 ,數據庫中是否已存在該條數據呢?就判斷提供的主鍵,在表中是否已存在
// , foreignKeys = {
//外鍵,一般用於多表數據查詢.可以配置多個外鍵
//ForeignKey用來設置關聯表數據更新時所進行的操作,比如可以在@ForeignKey注解中設置onDelete=CASCADE,這樣當Cache表中某個對應記錄被刪除時,ForeignTable表的所有相關記錄也會被刪除掉。
//對於@Insert(OnConflict=REPLACE)注解,SQLite是進行REMOVE和REPLACE操作,而不是UPDATE操作,這個可能影響到foreign key的約束。
//value:關聯查詢的表的Java.class,這里給定ForeignTable.class
//parentColumns:與之關聯表ForeignTable表中的列名
//childColumns:本表的列的名稱,必須要和parentColumns個數一致。這兩個可以理解為根據cache表中的那個字段去比對ForeignTable表中的那個字段,認為是有關聯關系的數據。
//onDelete:關聯表中某條記錄被delete或update時,本表應該怎么做:
// NO_ACTION:什么也不做,
// RESTRICT:本表跟parentColumns有關系的數據會立刻刪除或更新,但不允許一對多的關系,
// SET_NULL:本表所跟parentColumns有關系的數據被設置為null值,
// SET_DEFAULT:本表所有跟parentColumns有關系的數據被設置為默認值,也是null值
// CASCADE:本表所有跟parentColumns有關系的數據一同被刪除或更新
//onUpdate:本表中某條記錄被更新時,與之關聯的表應該怎么做
//deferred:本表某條記錄變更時,與之關聯表的數據變更是否要立即執行,還是等待本表事務處理完再來處理關聯表。默認是同時處理。
// @ForeignKey(value = ForeignTable.class,
// parentColumns = "foreign_key",
// childColumns = "key",
// onDelete = 1,
// onUpdate = 1,
// deferred = false)}
//本表中 那些字段 不需要 映射到表中
// , ignoredColumns = {"data"}
)
public class Cache implements Serializable {
//PrimaryKey 必須要有,且不為空,autoGenerate 主鍵的值是否由Room自動生成,默認false
@PrimaryKey(autoGenerate = false)
@NonNull
public String key;

@ColumnInfo(name = "_data"),指定該字段在表中的列的名字
public byte[] data;

@Embedded 對象嵌套,ForeignTable對象中所有字段 也都會被映射到cache表中,
//同時也支持ForeignTable 內部還有嵌套對象
public ForeignTable foreignTable;

}

public class ForeignTable implements Serializable {
@PrimaryKey
@NonNull
public String foreign_key;

//@ColumnInfo(name = "_data")
public byte[] foreign_data;
}
下面一個一個分析下這些注解的作用:

1、@Entity(tableName = "cache")注解,用於將一個java對象映射為數據庫表的注解

2、@PrimaryKeys = {"key"}//主鍵,一些策略邏輯會用到,比如插入一條數據時如果已存在,則更新否則算新的插入,那么怎么判斷 ,數據庫中是否已存在該條數據呢?就判斷提供的主鍵,在表中是否已存在

3、@ForeignKeys = {} 外鍵

一般用於多表數據查詢.可以配置多個外鍵,ForeignKey用來設置關聯表數據更新時所進行的操作,比如可以在@ForeignKey注解中設置onDelete=CASCADE,這樣當Cache表中某個對應記錄被刪除時,ForeignTable表的所有相關記錄也會被刪除掉。

4、indices = {@Index(value = "key", unique = false)}

本表索引,用於大量數據的查詢優化,unique有時候需要保證數據表的某個或者某些字段只有唯一的記錄,可以通過設置@Index注解的unique屬性實現。以下實例代碼實現了避免有兩條記錄包含一樣的key值。

5、inheritSuperIndices = false,如果該值為true,那么父類中標記的indices{}索引也會算作該表的索引

6、@ColumnInfo(name = "_data"),指定該字段在表中的列的名字

//@ColumnInfo(name = "_data"),指定該字段在表中的列的名字
public byte[] data;
如果不添加這個columnInfo注解,那么就會以這個字段data作為列名,添加后則以你所指定的_data作為列名。

7、@Embedded 將其他對象嵌套到表中,

例如另外一個ForeignTable對象中所有字段需要被映射到cache表中,同時也支持ForeignTable內部還有嵌套對象

步驟3、創建Dao操作數據表
對數據表進行增刪改查的操作,

import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;

@Dao
public interface CacheDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
long save(Cache cache);

/**
* 注意,冒號后面必須緊跟參數名,中間不能有空格。大於小於號和冒號中間是有空格的。
* select *from cache where【表中列名】 =:【參數名】------>等於
* where 【表中列名】 < :【參數名】 小於
* where 【表中列名】 between :【參數名1】 and :【參數2】------->這個區間
* where 【表中列名】like :參數名----->模糊查詢
* where 【表中列名】 in (:【參數名集合】)---->查詢符合集合內指定字段值的記錄
*
* @param key
* @return
*/

//如果是一對多,這里可以寫List<Cache>
@Query("select *from cache where `key`=:key")
Cache getCache(String key);

//只能傳遞對象昂,刪除時根據Cache中的主鍵 來比對的
@Delete
int delete(Cache cache);

//只能傳遞對象昂,刪除時根據Cache中的主鍵 來比對的
@Update(onConflict = OnConflictStrategy.REPLACE)
int update(Cache cache);
}
其中@Insert和@Update注解后面都有沖突處理onConflict = OnConflictStrategy.REPLACE,也即發生字段更新或者插入沖突時,該如何操作,提供給我們是替換還是回滾、中斷、失敗、還是忽略沖突等多種選擇。
————————————————
版權聲明:本文為CSDN博主「沙漠一只雕得兒得兒」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/cpcpcp123/article/details/113575155


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM