数据库的基本使用
添加依赖
//room
def room_version = "2.5.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
创建表
@Entity表示根据实体类创建数据表,如果有多个主键要使用primaryKeys = {}
@ColumnInfo 表示在数据表中的名字
@Ignore 表示不在数据表创建此字段
@PrimaryKey 主键
@Entity
public class Word {
@PrimaryKey
@ColumnInfo(name = "id")
private int id;
@ColumnInfo(name = "word")
private String word;
@ColumnInfo(name = "wordCH")
private String wordCH;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public String getWordCH() {
return wordCH;
}
public void setWordCH(String wordCH) {
this.wordCH = wordCH;
}
}
创建DAO
每一个表都对应一个dao。
@Dao
public interface WordDao {
@Query("select * from word")
List<Word> getAll();
@Insert
void insert(Word... words);
@Query("delete from word where wordCh = :wordCH ")
void deleteWord(String wordCH);
}
创建数据库
创建一个抽象类,设置要创建的数据表,数据版本,数据库名称,DAO。
entities 表示数据库中有哪些表
@Database(entities = {Word.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public static MyDatabase myDatabase;
public static synchronized MyDatabase getInstence(Context context) {
if (myDatabase == null) {
myDatabase = Room.databaseBuilder(context, MyDatabase.class, "my.db")
.build();
}
return myDatabase;
}
/**
* 声明dao
* @return
*/
public abstract WordDao getWordDao();
}
对数据库进行增删改查操作,必须要在子线程中。这里向数据库中插入了一条数据,又从数据库中进行了查寻并输出。代码如下:
new Thread(new Runnable() {
@Override
public void run() {
MyDatabase myDatabase = MyDatabase.getInstence(getApplicationContext());
Word word = new Word();
word.setId(1);
word.setWord("hello");
word.setWordCH("你好");
myDatabase.getWordDao().insert(word);
List<Word> wordList = myDatabase.getWordDao().getAll();
for (Word word1 : wordList) {
Log.d("Word", word1.toString());
}
}
}).start();
Room与LiveData、ViewMode结合使用
但数据发生变化时,总是需要启动一个线程去查询数据,这很麻烦,于是有了更好的处理方案。
我们将获取到的List用livedata包装起来。
@Dao
public interface WordDao {
........
@Query("select * from word")
LiveData<List<Word>> getAll();
}
创建WordViewModel
AndroidViewModel 与ViewModel不同点在于有没有context。
public class WordViewModel extends AndroidViewModel {
private MyDatabase myDatabase;
private LiveData<List<Word>> listLiveData;
public WordViewModel(@NonNull Application application) {
super(application);
WordDao wordDao = myDatabase.getWordDao();
listLiveData = wordDao.getAll();
}
public LiveData<List<Word>> getListLiveData() {
return listLiveData;
}
}
监听数据
wordViewModel = new ViewModelProvider(this).get(WordViewModel.class);
wordViewModel.getListLiveData().observe(this, new Observer<List<Word>>() {
@Override
public void onChanged(List<Word> words) {
}
});
当对数据库进行增加、删除或者修改时,onChanged方法会被调用。
使用migration升级
当数据库添加表,或者修改字段时,需要做一些调整,对数据库进行升级。
表示数据从版本1升级到版本2
public static Migration migration = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
}
};
1->3这种升级,room会判断有没有从1到3的升级方案,如果有,则直接升级;如果没有则room会按照1->2,2->3升级。
写完Migration 需要添加。
@Database(entities = {Word.class}, version = 2)
public abstract class MyDatabase extends RoomDatabase {
public static MyDatabase myDatabase;
public static synchronized MyDatabase getInstence(Context context) {
if (myDatabase == null) {
myDatabase = Room.databaseBuilder(context, MyDatabase.class, "my.db")
.addMigrations(migration)
.build();
}
return myDatabase;
}
public static Migration migration = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
}
};
.........
}
Schema文件
每次数据库升级都会生成一个Schema文件,这是一个json文件,包含了数据库的所有信息。查看它,能清楚地知道数据库每版变更的情况。
设置Schema导出路径
class RoomSchemaArgProvider implements CommandLineArgumentProvider {
@InputDirectory
@PathSensitive(PathSensitivity.RELATIVE)
File schemaDir
RoomSchemaArgProvider(File schemaDir) {
this.schemaDir = schemaDir
}
@Override
Iterable<String> asArguments() {
// Note: If you're using KSP, you should change the line below to return
// ["room.schemaLocation=${schemaDir.path}"]
return ["-Aroom.schemaLocation=${schemaDir.path}"]
}
}
android {
defaultConfig {
.......
/*room数据库需要*/
javaCompileOptions {
annotationProcessorOptions {
compilerArgumentProviders(
new RoomSchemaArgProvider(new File(projectDir, "schemas"))
)
}
}
}
}
预填充数据库createFromAsset、createFromFile
createFromFile用来作用域目录中的路径。
createFromAsset用来传输Asset中的路径
根据数据库表创建数据库,添加数据,导出db文件,存放与Asset文件中。
@Database(entities = {Word.class}, version = 2)
public abstract class MyDatabase extends RoomDatabase {
public static MyDatabase myDatabase;
public static synchronized MyDatabase getInstence(Context context) {
if (myDatabase == null) {
myDatabase = Room.databaseBuilder(context, MyDatabase.class, "my.db")
.addMigrations(migration)
.createFromAsset("my.db")//预填充数据库
.build();
}
return myDatabase;
}
......
}