- @Query : 包含所有Sqlite语句操作。
- @Insert : 标注数据库的插入操作。
- @Delete : 标注数据库的删除操作。
- @Update : 标注数据库的更新操作。
@Dao
public interface PersonDao {
//查询所有数据
@Query(“Select * from person”)
List getAll();
//删除全部数据
@Query(“DELETE FROM person”)
void deleteAll();
//一次插入单条数据 或 多条
// @Insert(onConflict = OnConflictStrategy.REPLACE),这个是干嘛的呢,下面有详细教程
@Insert
void insert(Person… persons);
//一次删除单条数据 或 多条
@Delete
void delete(Person… persons);
//一次更新单条数据 或 多条
@Update
void update(Person… persons);
//根据字段去查找数据
@Query(“SELECT * FROM person WHERE uid= :uid”)
Person getPersonByUid(int uid);
//一次查找多个数据
@Query(“SELECT * FROM person WHERE uid IN (:userIds)”)
List loadAllByIds(List userIds);
//多个条件查找
@Query(“SELECT * FROM person WHERE name = :name AND age = :age”)
Person getPersonByNameage(String name, int age);
}
这里唯一特殊的就是@Insert。其有一段介绍:对数据库设计时,不允许重复数据的出现。否则,必然造成大量的冗余数据。实际上,难免会碰到这个问题:冲突。当我们像数据库插入数据时,该数据已经存在了,必然造成了冲突。该冲突该怎么处理呢?在@Insert注解中有conflict用于解决插入数据冲突的问题,其默认值为OnConflictStrategy.ABORT。对于OnConflictStrategy而言,它封装了Room解决冲突的相关策略。
- OnConflictStrategy.REPLACE:冲突策略是取代旧数据同时继续事务
- OnConflictStrategy.ROLLBACK:冲突策略是回滚事务
- OnConflictStrategy.ABORT:冲突策略是终止事务
- OnConflictStrategy.FAIL:冲突策略是事务失败
- OnConflictStrategy.IGNORE:冲突策略是忽略冲突
这里比如在插入的时候我们加上了OnConflictStrategy.REPLACE,那么往已经有uid=1的person表里再插入uid =1的person数据,那么新数据会覆盖就数据。如果我们什么都不加,那么久是默认的OnConflictStrategy.ABORT,重复上面的动作,你会发现,程序崩溃了。也就是上面说的终止事务。其他大家可以自己试试
四、Database:数据库持有者 & 数据库版本管理者
直接上代码
//注解指定了database的表映射实体数据以及版本等信息(后面会详细讲解版本升级)
@Database(entities = {Person.class, Clothes.class}, version = 1)
public abstract class AppDataBase extends RoomDatabase {
public abstract PersonDao getPersonDao();
public abstract ClothesDao getClothesDao();
}
五、Room:数据库的创建者 & 负责数据库版本更新的具体实现者
Room创建我们的AppDataBase,我们把它封装成单例,省的每次都去执行一遍,耗性能
public class DBInstance {
//private static final String DB_NAME = “/sdcard/LianSou/room_test.db”;
private static final String DB_NAME = “room_test”;
public static AppDataBase appDataBase;
public static AppDataBase getInstance(){
if(appDataBasenull){
synchronized (DBInstance.class){
if(appDataBasenull){
appDataBase = Room.databaseBuilder(MyApplication.getInstance(),AppDataBase.class, DB_NAME)
//下面注释表示允许主线程进行数据库操作,但是不推荐这样做。
//我这里是为了Demo展示,稍后会结束和LiveData和RxJava的使用
.allowMainThreadQueries()
.build();
}
}
}
return appDataBase;
}
}
做完这一切,那么我们的准备工作就做完了。让我们来插入一条数据
Person person_ = new Person(“Room”, 18);
DBInstance.getInstance().getPersonDao().insert(person_);
5.1、额外知识点
这里怎么查看db数据呢?首先我们把db文件存在手机内存里,记得打开存储权限,就是在上面代码里指定路径
private static final String DB_NAME = “/sdcard/LianSou/room_test.db”;
插入数据后,就会在手机内存卡生成db文件。
拿到db文件,怎么办呢。用插件!!Database Navigator,插件教程
六、数据库版本升级
这里的意思比如我已经往person表存里数据。但是我要增加字段,或者是增加索引。如果你直接写上去,你会发现,你再使用数据库的时候,会直接崩溃。怎么办呢,用过greendao的人都知道,我们要升级数据库版本
@Entity
public class Person {
//…省略部分代码,便于理解。
//这里给Person加上一个儿子
}
然后来到我们的Database类里,把版本信息改下,并增添一个Migration 类,告诉Room是哪张表改了什么东西
//修改版本信息为2
@Database(entities = {Person.class, Clothes.class}, version = 2)
public abstract class AppDataBase extends RoomDatabase {
public abstract PersonDao getPersonDao();
public abstract ClothesDao getClothesDao();
//数据库变动添加Migration,简白的而说就是版本1到版本2改了什么东西
public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
//告诉person表,增添一个String类型的字段 son
database.execSQL(“ALTER TABLE person ADD COLUMN son TEXT”);
}
};
}
关于版本更新的execSQL里的用法,可以参考Room升级。也可以自行度娘,网上很多
最后来到我们的Room里:
public class DBInstance {
// private static final String DB_NAME = “/sdcard/LianSou/room_test.db”;
private static final String DB_NAME = “room_test”;
public static AppDataBase appDataBase;
public static AppDataBase getInstance(){
if(appDataBasenull){
synchronized (DBInstance.class){
if(appDataBasenull){
return Room.databaseBuilder(MyApplication.getInstance(),AppDataBase.class, DB_NAME)
.allowMainThreadQueries()
//加上版本升级信息
.addMigrations(AppDataBase.MIGRATION_1_2)
.build();
}
}
}
return appDataBase;
}
}
做完以上操作后,我们来运行下项目看看。成功,打开数据看看(本文demo里,我把升级代码注释了,想测试的可自行打开):
七、Room 结合RxJava使用(需要先了解RxJava的使用)
首先看我们DBInstance里的Room创建我们的AppDataBase,这句代码
//下面注释表示允许主线程进行数据库操作,但是不推荐这样做。
.allowMainThreadQueries()
我们,把这句代码注释掉,其他不变,运行下代码,看看。结果会报错,报错信息如下
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.
这个时候,我们来结合RxJava来使用下,这样数据操作可以放在子线程,回调可以切换到主线程更改UI。首先是引入我们的依赖
implementation ‘android.arch.persistence.room:rxjava2:2.1.4’
//下面这个是配合rxjava使用的
implementation ‘io.reactivex.rxjava2:rxandroid:2.0.2’
这里需要注意2点:
1、在数据库执行**@Insert、@Delete、@Update**操作时候可以使用(注意是可以使用)RxJava里的类型有:Completable,Single,Maybe
2、在执行**@Query**操作时,可以返回的类型有:Single,Maybe,Observable,Flowable
这里需要注意:
- 你想一次性查询就用: Single,Maybe;这样的话,如果查询数据库之后数据库有改变时,后面不会有任何事务。
- 如果你是想观察数据库: Observable,Flowable。那么当已经查询数据了,如果之后数据还有改变,那么将自动执行Observable,Flowable里观察的代码。意思就是对数据可持续观察,实时显示数据库中最新的数据
这里可能大家对Single,Maybe,Completable,Observable,Flowable不大了解,这里做个简单介绍:
1、Completable:只有onComplete和onError方法,即只有“完成”和“错误”两种状态,不会返回具体的结果。
2、Single:其回调为onSuccess和onError,查询成功会在onSuccess中返回结果,需要注意的是,如果未查询到结果,即查询结果为空,会直接走onError回调,抛出EmptyResultSetException异常。
3、Maybe:其回调为onSuccess,onError,onComplete,查询成功,如果有数据,会先回调onSuccess再回调onComplete,如果没有数据,则会直接回调onComplete。
4、Flowable/Observable:这是返回一个可观察的对象,查询的部分有变化时,都会回调它的onNext方法,没有数据变化的话,不回调。直到Rx流断开。
这里为了demo的清晰化,我们再建一个Dog表。这里申明一点,在数据库执行这些操作的时候@Insert、@Delete、@Update,不能直接把返回类型写成RxJava返回,类型,不然会直接报
错误: Methods annotated with @Insert can return either void, long, Long, long[], Long[] or List.
所以现在好多网上关于这部分,也没有讲清楚。如果有清楚的同学请指正。请看Dao类:
结语
网上高级工程师面试相关文章鱼龙混杂,要么一堆内容,要么内容质量太浅, 鉴于此我整理了上述安卓开发高级工程师面试题以及答案。希望帮助大家顺利进阶为高级工程师。
目前我就职于某大厂安卓高级工程师职位,在当下大环境下也想为安卓工程师出一份力,通过我的技术经验整理了面试经常问的题,答案部分是一篇文章或者几篇文章,都是我认真看过并且觉得不错才整理出来。
大家知道高级工程师不会像刚入门那样被问的问题一句话两句话就能表述清楚,所以我通过过滤好文章来帮助大家理解。
现在都说互联网寒冬,其实只要自身技术能力够强,咱们就不怕!我这边专门针对Android开发工程师整理了一套【Android进阶学习视频】、【全套Android面试秘籍】、【Android知识点PDF】。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
roid进阶学习视频】、【全套Android面试秘籍】、【Android知识点PDF】。**
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!