Google 架构之Room数据库基本使用


Room提供了一个基于SQLite的抽象层,以便在利用SQLite的全部功能的同时实现更强大的数据库访问。

Room可帮助您在运行应用程序的设备上创建应用程序数据的缓存。此缓存作为应用程序的唯一事实来源,允许用户在应用程序中查看关键信息的一致副本,无论用户是否具有网络连接。

Room 主要组成包括三个部分

Database: 包含数据库持有者,并作为应用程序持久关系数据的基础连接的主要访问点。

@Database 注解的类应满足以下条件:

  • 是一个扩展的抽象类 RoomDatabase。
  • 在注解中包括与数据库关联的Entity列表。
  • 包含一个具有无参的抽象方法,并返回带注释的类 @Dao.

Entity:表示数据库中的表。
DAO:包含用于访问数据库的方法。

三者之间的关系 :

使用

环境需求:Android Studio 2.3 或更高版本
添加依赖

implementation 'android.arch.persistence.room:runtime:1.1.1'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
//如果配合rxjiava使用需要添加
implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

具体示例

创建实体类

Repo :

@Entity  //添加Entity 表示数据库中的表
public class Repo {
    @PrimaryKey  //主键
    public int id;
    public String name;
    public String url;
    public int age;
    public boolean isNew;   

    public Repo() {
        age = 1;
    }

    public Repo(int id, String name, String url) {
        this.id = id;
        this.name = name;
        this.url = url;
        age=0;
    }
    //getter and setter 省略 
    ......
        @Override    
        public String toString() {
           return "Repo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", url='" + url + '\'' +
                ", age=" + age +
                ", isNew=" + isNew +
            '}';
    }
}
创建Dao

RepoDao

@Dao
public interface RepoDao {

    @Query("SELECT * FROM Repo")
    List<Repo> getAllRepos();

    @Insert(onConflict = REPLACE)
    void insert(Repo... repos);

    @Update
    void update(Repo... repos);

    @Delete
    void delete(Repo... repos);

    @Query("SELECT*FROM REPO WHERE id = :id")
    Repo qurery(int id);
}
创建数据库(Database)

RepoDatabase

@Database(entities = Repo.class, version = 3)
public abstract class RepoDatabase extends RoomDatabase {
    
    private static final String DB_NAME = "repoDatabase.db";
    private static volatile RepoDatabase instance;

    static synchronized RepoDatabase getInstance(Context context) {
        if (instance == null) {
            instance = create(context);
        }
        return instance;
    }

    private static RepoDatabase create(final Context context) {
        return Room.databaseBuilder(
                context,
                RepoDatabase.class,
                DB_NAME)
                .build();
    }

    public abstract RepoDao getRepoDao();

}

注意:由于创建 RoomDatabase 示例比较耗费资源,如果您的应用程序在单个进程中运行,则在实例化AppDatabase对象时应遵循单例设计模式。

这样整个数据库就创建完成了,接下来就是对数据库操作了。

需要注意的是:
对数据库的所有操作需要在子线程中
对数据库的所有操作需要在子线程中
对数据库的所有操作需要在子线程中

这里使用Rxjava 配合线程切换使用。把相关的具体操作封装在一个RepoUtils类中 :

public class RepoUtils {

    public void insert(final Context context, final Repo repo) {
        Observable.create(new ObservableOnSubscribe<Void>() {
            @Override
            public void subscribe(ObservableEmitter<Void> emitter) throws Exception {
                RepoDatabase
                        .getInstance(context)
                        .getRepoDao()
                        .insert(repo);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe();
    }

    public Observable<List<Repo>> getAll(final Context context) {
        return Observable.create(new ObservableOnSubscribe<List<Repo>>() {
            @Override
            public void subscribe(ObservableEmitter<List<Repo>> emitter) {
                emitter.onNext(RepoDatabase
                        .getInstance(context).getRepoDao().getAllRepos());
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<Repo> query(final Context context, final int repo) {
        return Observable.create(new ObservableOnSubscribe<Repo>() {
            @Override
            public void subscribe(ObservableEmitter<Repo> emitter) {
                Repo qurery = RepoDatabase.getInstance(context).getRepoDao().qurery(repo);
                if (qurery == null) {
                    Log.d("MainActivity", "this id:" + repo + "don't exist");
                    return;
                }
                emitter.onNext(qurery);
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }

    public void update(final Context context, final Repo repo) {
        Observable.create(new ObservableOnSubscribe<Void>() {
            @Override
            public void subscribe(ObservableEmitter<Void> emitter) {
                RepoDatabase.getInstance(context).getRepoDao().update(repo);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe();
    }

在MainActivity 中进行测试:

public class MainActivity extends AppCompatActivity {

    RepoUtils reposity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        reposity = new RepoUtils();
        findViewById(R.id.insert).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Repo repo = new Repo();
                repo.setId(1);
                repo.setName("");
                repo.setUrl("Tomurl");
                reposity.insert(MainActivity.this, repo);
            }
        });
        findViewById(R.id.getAll).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Disposable subscribe = reposity.getAll(MainActivity.this).subscribe(new Consumer<List<Repo>>() {
                    @Override
                    public void accept(List<Repo> repos) throws Exception {
                        Log.d("MainActivity", repos.toString());
                    }
                });
            }
        });

        findViewById(R.id.insertSame).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Repo repo = new Repo();
                repo.setId(1);
                repo.setName("JERRY");
                reposity.insert(MainActivity.this, repo);
            }
        });

        findViewById(R.id.queryExist).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Disposable mainActivity = reposity.query(MainActivity.this, 1).subscribe(new Consumer<Repo>() {
                    @Override
                    public void accept(Repo repo) {
                        Log.d("MainActivity", repo.toString());
                    }
                });
            }
        });
        findViewById(R.id.queryNoExist).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Disposable mainActivity = reposity.query(MainActivity.this, 4).subscribe(new Consumer<Repo>() {
                    @Override
                    public void accept(Repo repo) {
                        Log.d("MainActivity", repo.toString());
                    }
                });
            }
        });
        findViewById(R.id.update).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Repo repo = new Repo();
                repo.setId(1);
                repo.setName("WO");
                repo.setUrl("Tomurl");
                reposity.update(MainActivity.this, repo);
            }
        });
    }
}

insert: 插入一个ID=1 ,name="", url =“Tomurl”
insertSame: 插入一个ID=1,name=“JERRY” url=null
getAll: 获取数据库中的所有数据
queryExist :获取ID=1 的一条数据
queryNoExist:获取一个不存在的ID
update:更新ID=1 的数据

log输出:

MainActivity: [Repo{id=1, name='', url='Tomurl', age=1, isNew=false}]   //insert
MainActivity: [Repo{id=1, name='JERRY', url='null', age=1, isNew=false}]  //insertSame
MainActivity: Repo{id=1, name='JERRY', url='null', age=1, isNew=false}  //getAll
MainActivity: [Repo{id=1, name='JERRY', url='null', age=1, isNew=false}] //queryExist
MainActivity: this id:4don't exist //queryNoExist
MainActivity: [Repo{id=1, name='WO', url='Tomurl', age=1, isNew=false}]  //update   getAll

从上面的操作和打印日志可以我们在回到RepoDap 中

@Insert(onConflict = REPLACE)
void insert(Repo... repos);
@Update
void update(Repo... repos);

如果有相同的ID的数据,冲突解决办法

OnConflictStrategy.REPLACE   //替换老数据
OnConflictStrategy.ROLLBACK  // 回滚事务
OnConflictStrategy.ABORT  //放弃事务
OnConflictStrategy.FAIL //失败事务
OnConflictStrategy.IGNORE  //忽略冲突

如遇到数据库升级问题可以参考另一篇文章Room 数据库升级问题 java.lang.IllegalStateException: Migration didn’t properly handle xxx希望能够帮助到您。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值