Room其實就是一個orm,抽象了SQLite的使用,可是它做爲Android的親兒子orm,而且原生支持LiveData和Rxjava嵌套使用,學習一下仍是不錯的。html
Room有3個主要組件java
allprojects {
repositories {
jcenter()
google()
}
}
複製代碼
dependencies {
// Room
implementation "android.arch.persistence.room:runtime:1.0.0"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
}
複製代碼
班級表react
@Entity(tableName = "tb_class")
public class ClassEntity {
@PrimaryKey
private long id;
}
複製代碼
學生表android
//指示數據表實體類
@Entity(tableName = "tb_student",//定義表名
indices = @Index(value = {"name", "sex"}, unique = true),//定義索引
foreignKeys = {@ForeignKey(entity = ClassEntity.class,
parentColumns = "id",
childColumns = "class_id")})//定義外鍵
public class StudentEntity {
@PrimaryKey //定義主鍵
private long id;
@ColumnInfo(name = "name")//定義數據表中的字段名
private String name;
@ColumnInfo(name = "sex")
private int sex;
@Ignore//指示Room須要忽略的字段或方法
private String ignoreText;
@ColumnInfo(name = "class_id")
private String class_id;
//setter and getter
}
複製代碼
public @interface Entity {
//定義表名
String tableName() default "";
//定義索引
Index[] indices() default {};
//設爲true則父類的索引會自動被當前類繼承
boolean inheritSuperIndices() default false;
//定義主鍵
String[] primaryKeys() default {};
//定義外鍵
ForeignKey[] foreignKeys() default {};
}
複製代碼
public @interface Index {
//定義須要添加索引的字段
String[] value();
//定義索引的名稱
String name() default "";
//true-設置惟一鍵,標識value數組中的索引字段必須是惟一的,不可重複
boolean unique() default false;
}
複製代碼
public @interface ForeignKey {
//引用外鍵的表的實體
Class entity();
//要引用的外鍵列
String[] parentColumns();
//要關聯的列
String[] childColumns();
//當父類實體(關聯的外鍵表)從數據庫中刪除時執行的操做
@Action int onDelete() default NO_ACTION;
//當父類實體(關聯的外鍵表)更新時執行的操做
@Action int onUpdate() default NO_ACTION;
//在事務完成以前,是否應該推遲外鍵約束
boolean deferred() default false;
//給onDelete,onUpdate定義的操做
int NO_ACTION = 1;
int RESTRICT = 2;
int SET_NULL = 3;
int SET_DEFAULT = 4;
int CASCADE = 5;
@IntDef({NO_ACTION, RESTRICT, SET_NULL, SET_DEFAULT, CASCADE})
@interface Action {
}
}
複製代碼
@Dao
public interface StudentDao {
@Query("SELECT * FROM StudentEntity")
List<StudentEntity> getAll();
@Query("SELECT * FROM StudentEntity WHERE id IN (:ids)")
List<StudentEntity> getAllByIds(long[] ids);
@Insert
void insert(StudentEntity... entities);
@Delete
void delete(StudentEntity entity);
@Update
void update(StudentEntity entity);
}
複製代碼
@insert, @Update均可以執行事務操做,定義在OnConflictStrategy註解類中數據庫
public @interface Insert {
//定義處理衝突的操做
@OnConflictStrategy
int onConflict() default OnConflictStrategy.ABORT;
}
複製代碼
public @interface OnConflictStrategy {
//策略衝突就替換舊數據
int REPLACE = 1;
//策略衝突就回滾事務
int ROLLBACK = 2;
//策略衝突就退出事務
int ABORT = 3;
//策略衝突就使事務失敗
int FAIL = 4;
//忽略衝突
int IGNORE = 5;
}
複製代碼
@Database(entities = {StudentEntity.class}, version = 1)
public abstract class RoomDemoDatabase extends RoomDatabase {
public abstract StudentDao studentDao();
}
複製代碼
RoomDemoDatabase database = Room.databaseBuilder(getApplicationContext(),
RoomDemoDatabase.class, "database_name")
.build();
複製代碼
生成數據庫實例的其餘操做數組
Room.databaseBuilder(getApplicationContext(),
RoomDemoDatabase.class, "database_name")
.addCallback(new RoomDatabase.Callback() {
//第一次建立數據庫時調用,可是在建立全部表以後調用的
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
}
//當數據庫被打開時調用
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
}
})
.allowMainThreadQueries()//容許在主線程查詢數據
.addMigrations()//遷移數據庫使用,下面會單獨拿出來說
.fallbackToDestructiveMigration()//遷移數據庫若是發生錯誤,將會從新建立數據庫,而不是發生崩潰
.build();
複製代碼
Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
+ "`name` TEXT, PRIMARY KEY(`id`))");
}
};
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE Book "
+ " ADD COLUMN pub_year INTEGER");
}
};
複製代碼
有時,您但願將一個實體或普通的之前的Java對象(POJO)做爲數據庫邏輯中的一個完整的總體來表示,即便該對象包含幾個字段。在這些狀況下,您可使用@Embedded來表示一個對象,您但願將其分解爲表中的子字段。而後能夠像對其餘單個列同樣查詢嵌入式字段架構
class Address {
public String street;
public String state;
public String city;
@ColumnInfo(name = "post_code")
public int postCode;
}
@Entity
class User {
@PrimaryKey
public int id;
public String firstName;
@Embedded
public Address address;
}
複製代碼
這樣user表中的字段就包含了id
, firstName
, street
, state
, city
, 和 post_code
ide
注意
:嵌入式字段還能夠包含其餘嵌入式字段post
若是一個實體具備相同類型的多個內嵌字段,則能夠經過設置前綴屬性(prefix)使每一個列保持唯一。而後將所提供的值添加到嵌入對象中每一個列名的開頭學習
@Embedded(prefix = "foo_")
Coordinates coordinates;
複製代碼
LiveData
一塊兒使用添加依賴
// ReactiveStreams support for LiveData
implementation "android.arch.lifecycle:reactivestreams:1.0.0"
複製代碼
修改返回類型
@Dao
public interface MyDao {
@Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
public LiveData<List<User>> loadUsersFromRegionsSync(List<String> regions);
}
複製代碼
添加依賴
// RxJava support for Room
implementation "android.arch.persistence.room:rxjava2:1.0.0"
複製代碼
修改返回類型
@Dao
public interface MyDao {
@Query("SELECT * from user where id = :id LIMIT 1")
public Flowable<User> loadUserById(int id);
}
複製代碼
@Dao
public interface MyDao {
@Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")
public Cursor loadRawUsersOlderThan(int minAge);
}
複製代碼
定義轉換類,@TypeConverter註解定義轉換的方法
public class Converters {
@TypeConverter
public static Date fromTimestamp(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long dateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
複製代碼
@TypeConverters註解,告知數據庫要依賴哪些轉換類
@Database(entities = {User.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
複製代碼
使用這些轉換器,您能夠在其餘查詢中使用您的自定義類型,正如您將使用基本類型同樣,以下代碼所示
@Entity
public class User {
...
private Date birthday;
}
複製代碼
@Dao
public interface UserDao {
...
@Query("SELECT * FROM user WHERE birthday BETWEEN :from AND :to")
List<User> findUsersBornBetweenDates(Date from, Date to);
}
複製代碼
在編譯時,將數據庫的模式信息導出到JSON文件中,這樣可有利於咱們更好的調試和排錯
build.gradle
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
}
}
複製代碼
您應該將導出的JSON文件(表示數據庫的模式歷史記錄)存儲在您的版本控制系統中,由於它容許爲測試目的建立您的數據庫的舊版本