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;
}
}