Android-Room數(shù)據(jù)庫-多表查詢(Relationships)
Android-Room自定義類型(TypeConverter)
Android—Room?數(shù)據(jù)庫遷移(Migration)
Android — Room?數(shù)據(jù)庫跳躍式升級(Migration)
Android—Room 通用封裝
前言
Google終于發(fā)布了一個和SQLite相關(guān)的庫了??????。之前一直都是在SQLite、XUtils、greenDao、Realm這些數(shù)據(jù)庫之間來回折騰?,F(xiàn)在終于有一個更“正統(tǒng)”數(shù)據(jù)庫了。
Room是什么?
Room是一個持久性數(shù)據(jù)庫。
Room持久性庫提供了SQLite的抽象層,以便在充分利用SQLite的同時允許流暢的數(shù)據(jù)庫訪問。
為什么會選擇Room?
前面我也說到了現(xiàn)在也有不少開源的數(shù)據(jù)庫給大家使用,那為什么我們還要去學(xué)習(xí)使用這個庫呢?當(dāng)然不是我前面說的“正不正統(tǒng)”的原因了。
因為Room有下面幾個優(yōu)點:
① SQL查詢在編譯時就會驗證 - 在編譯時檢查每個@Query和@Entity等,這就意味著沒有任何運行時錯誤的風(fēng)險可能會導(dǎo)致應(yīng)用程序崩潰(并且它不僅檢查語法問題,還會檢查是否有該表)
② 較少的模板代碼
③ 與 LiveData集成
該如何使用它?
1、在app/build.gradle中添加以下依賴
implementation 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
你可以點擊這里查看最新依賴版本號
2、創(chuàng)建JavaBean
@Entity
public class User {
@PrimaryKey(autoGenerate = true)//主鍵是否自動增長,默認為false
private int id;
private String name;
private int age;
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;
}
//這里的getter/setter方法是必須的
//這里的getter/setter方法是必須的
//這里的getter/setter方法是必須的
//重要的事說三遍
}
- 這里需要使用
@Entity來注解該類 - 至少要有一個主鍵
@PrimaryKey
3、創(chuàng)建Dao
接下來,需要為我們的實體創(chuàng)建DAO。 DAO代表數(shù)據(jù)訪問對象,所以它是告訴我們的數(shù)據(jù)庫如何操作數(shù)據(jù)的一種方式:
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
List<User> getAllUsers();
@Insert
void insert(User... users);
@Update
void update(User... users);
@Delete
void delete(User... users);
}
- 使用
@Dao注解該接口 -
@Insert,@Update,@Delete,@Query代表我們常用的插入、更新、刪除、查詢數(shù)據(jù)庫操作
@Insert, @Update, @Delete可以傳入多種不同的參數(shù)。例如:
@Insert
void insert(User... users);
@Insert
void insert(User user);
@Insert
void insert(List<User> userLists);
同理,@Query也可以返回多種不同的類型。
@Query("SELECT * FROM user")
List<User> getAllUsers();
@Query("SELECT * FROM user WHERE id=:id")
User getUser(int id);
@Query("SELECT * FROM user")
Cursor getUserCursor();
當(dāng)然,除了這些我們還可以傳入一些限制符進去。例如,
@Query("SELECT * FROM user WHERE age=:age")
List<User> getUsersByAge(int age);
@Query("SELECT * FROM user WHERE age=:age LIMIT :max")
List<User> getUsersByAge(int max, int... age);
4、創(chuàng)建數(shù)據(jù)庫
@Database(entities = { User.class }, version = 1,exportSchema = false)
public abstract class UserDatabase extends RoomDatabase {
private static final String DB_NAME = "UserDatabase.db";
private static volatile UserDatabase instance;
static synchronized UserDatabase getInstance(Context context) {
if (instance == null) {
instance = create(context);
}
return instance;
}
private static UserDatabase create(final Context context) {
return Room.databaseBuilder(
context,
UserDatabase.class,
DB_NAME).build();
}
public abstract UserDao getUserDao();
}
這里使用@Database注解該類并添加了表名、數(shù)據(jù)庫版本(每當(dāng)我們改變數(shù)據(jù)庫中的內(nèi)容時它都會增加),所以這里使用exportSchema = false
注意:除了添加表映射的類以及和數(shù)據(jù)庫版本外,還要添加
exportSchema = false否則會報警告。
Error:(10, 17) 警告: Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provideroom.schemaLocationannotation processor argument OR set exportSchema to false.
我們抽象了getUserDao()方法,這是必要的。
5、使用數(shù)據(jù)庫
我們終于能夠操作我們的數(shù)據(jù)庫了。但是所有的操作必須在后臺線程中完成。你可以通過使用AsyncTask,Thread,Handler,RxJava或其它方式來完成。
如果沒有在后臺線程執(zhí)行,并且也沒有說明可以在主線程操作的話,就會報以下錯誤。
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
例如,我們可以像下面這樣插入數(shù)據(jù)
User user=new User();
user.setName("name1");
user.setAge(18);
UserDatabase
.getInstance(context)
.getUserDao()
.insert(user);
或者這樣
List<User> allUsers = UserDatabase
.getInstance(RoomActivity.this)
.getUserDao()
.getAllUsers();
好了,基本的使用的方式就這些了。未完待續(xù)