1.關于room
room是google官方開發的對象關系映射(ORM)庫架構,采用注解的方式,讓你通路資料庫更加穩健,提升資料庫性能。
- 官網說明
- 中文翻譯指南
- 官方案例
2.導入room
implementation "android.arch.persistence.room:runtime:1.1.1"
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"
3.實作資料庫操作的步驟
1. 必須先建立一個需要映射的實體類,用@Entity進行注解
@Entity
public class Anime {
/**
* 動漫名
* 如果是字元串做主鍵,記得加@NonNull,不然會報錯
*/
@NonNull
@PrimaryKey
private String name;
/**
* 動漫類型
*/
private String type;
/**
* 放送時間
*/
private String playDate;
/**
* 集數
*/
private int episode;
getter、setter省略...
}
2. 建立一個操作實體類的dao接口,用@Dao進行注解
@Dao
public interface AnimeDao {
@Query("SELECT * FROM anime")
List<Anime> getAllAnime(); //加載所有動漫資料
@Query("SELECT * FROM anime WHERE name = :name")
Anime loadAnimeByName(String name); //根據名字加載動漫
@Insert
void insertOneAnime(Anime anime); //插入一條動漫資訊
@Insert
void insertMultiAnimes(Anime... animes); //插入多條動漫資訊
@Update(onConflict = OnConflictStrategy.REPLACE)
int updateUsers(Anime... animes); //更新動漫資訊,當有沖突時則進行替代
@Delete
void deleteAnime(Anime anime);
}
3. 建立一個抽象類,添加@Database注解
@Database(entities = {Anime.class},version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract AnimeDao animeDao();
}
4. 建立RoomDatabase執行個體,在application中初始化,建議是單例
public class MyApp extends Application {
private static MyApp mInstance;
private AppDatabase appDB;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
appDB = Room.databaseBuilder(this,AppDatabase.class,"anime_info")
.addMigrations()
.build();
}
public static MyApp getInstance(){
return mInstance;
}
public AppDatabase getAppDB(){
return appDB;
}
}
4.操作資料庫進行增删改查
增
animeDao.insertOneAnime(createOneAnime());
删
animeDao.deleteAnime(queryOneRecord());
改
Anime anime = queryOneRecord();
anime.setEpisode(100);
animeDao.updateUsers(anime);
查
private Anime queryOneRecord() {
Anime anime = animeDao.loadAnimeByName("青春豬頭少年不會夢到兔女郎學姐");
tvResult.setText(anime.toString());
return anime;
}
5.異常報錯
- 實體類定義中沒有加NonNull,因為它是字元串主鍵,為避免其為空,是以必須加上此限制
You must annotate primary keys with @NonNull. "name" is nullable. SQLite considers this a bug and Room does not allow it. See SQLite docs for details:
- 不允許在主線程中操作資料庫,可在建構RoomDatabase執行個體對象中,加入
,這是預設不許在主線程中連接配接資料庫。allowMainThreadQueries()
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
變成這樣即可
appDB = Room.databaseBuilder(this,AppDatabase.class,"anime_info")
.addMigrations()
.allowMainThreadQueries()
.build();
6.檢視資料庫
用SQLite Expert Personal 3打開剛建立并進行操作過的資料庫,看是否正常。

打開第一個檔案anime_info,注意這裡在建構RoomDatabase執行個體時沒加字尾db,是以看到的檔案也沒有db字尾。
可以看到資料庫表正确地建立了,資料也有寫入。
最後,附上界面圖和activity代碼,寫的很粗糙,多次點選會崩潰,因為有沖突發生時是以異常形式處理的,更深層次的應用有機會再寫。
package cn.pigdreams.blogdemo.roomdemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.List;
import cn.pigdreams.blogdemo.MyApp;
import cn.pigdreams.blogdemo.R;
public class RoomDemoActivity extends AppCompatActivity implements View.OnClickListener {
private Button button;
private Button button2;
private Button button3;
private Button button4;
private Button button5;
private Button button6;
private TextView tvResult;
private AnimeDao animeDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_room_demo);
button = findViewById(R.id.button);
button2 = findViewById(R.id.button2);
button3 = findViewById(R.id.button3);
button4 = findViewById(R.id.button4);
button5 = findViewById(R.id.button5);
button6 = findViewById(R.id.button6);
tvResult = findViewById(R.id.tv_result);
button.setOnClickListener(this);
button2.setOnClickListener(this);
button3.setOnClickListener(this);
button4.setOnClickListener(this);
button5.setOnClickListener(this);
button6.setOnClickListener(this);
//拿到資料庫操作對象
animeDao = MyApp.getInstance().getAppDB().animeDao();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
//增加一條動漫記錄
animeDao.insertOneAnime(createOneAnime());
break;
case R.id.button2:
//删除一條記錄
animeDao.deleteAnime(queryOneRecord());
queryAllRecord();
break;
case R.id.button3:
//更新一條記錄
updateRecord();
break;
case R.id.button4:
//查詢所有記錄
queryAllRecord();
break;
case R.id.button5:
//增加多條動漫記錄
animeDao.insertMultiAnimes(createMutilAnime());
break;
case R.id.button6:
//查詢一條記錄
queryOneRecord();
break;
}
}
private void updateRecord() {
Anime anime = queryOneRecord();
anime.setEpisode(100);
animeDao.updateUsers(anime);
queryAllRecord();
}
private Anime queryOneRecord() {
Anime anime = animeDao.loadAnimeByName("青春豬頭少年不會夢到兔女郎學姐");
tvResult.setText(anime.toString());
return anime;
}
private void queryAllRecord() {
List<Anime> animeList = animeDao.getAllAnime();
tvResult.setText(animeList.toString());
}
private Anime createOneAnime(){
Anime anime = new Anime();
anime.setName("青春豬頭少年不會夢到兔女郎學姐");
anime.setType("奇幻&戀愛");
anime.setPlayDate("2018-10");
anime.setEpisode(13);
return anime;
}
private Anime[] createMutilAnime(){
Anime[] animes = new Anime[3];
Anime anime = new Anime();
anime.setName("超能力女兒");
anime.setType("魔幻日常");
anime.setPlayDate("2018-4");
anime.setEpisode(12);
Anime anime1 = new Anime();
anime1.setName("衛宮家今天的飯");
anime1.setType("美食");
anime1.setPlayDate("2018-1");
anime1.setEpisode(13);
Anime anime2 = new Anime();
anime2.setName("終将成為你");
anime2.setType("百合");
anime2.setPlayDate("2018-10");
anime2.setEpisode(13);
animes[0] = anime;
animes[1] = anime1;
animes[2] = anime2;
return animes;
}
}