接入方法

1、在接入 Room 的基础上,gradle 里加上 WCDB 的 room 组件

 dependencies {implementation 'com.tencent.wcdb:room:1.0.8'  // 代替 room-runtime,同时也不需要再引用 wcdb-androidannotationProcessor 'android.arch.persistence.room:compiler:1.1.1' // compiler 需要用 room 的
}

2、代码里面,打开 RoomDatabase 时,指定 WCDBOpenHelperFactory 作为 openFactory

QLiteCipherSpec cipherSpec = new SQLiteCipherSpec()  // 指定加密方式,使用默认加密可以省略.setPageSize(4096).setKDFIteration(64000);WCDBOpenHelperFactory factory = new WCDBOpenHelperFactory().passphrase("passphrase".getBytes())  // 指定加密DB密钥,非加密DB去掉此行.cipherSpec(cipherSpec)               // 指定加密方式,使用默认加密可以省略.writeAheadLoggingEnabled(true)       // 打开WAL以及读写并发,可以省略让Room决定是否要打开.asyncCheckpointEnabled(true);        // 打开异步Checkpoint优化,不需要可以省略AppDatabase db = Room.databaseBuilder(this, AppDatabase.class, "dbName") //dbName可以使用单独的名字或者绝对路径//.allowMainThreadQueries()   // 允许主线程执行DB操作,一般不推荐.openHelperFactory(factory)   // 重要:使用WCDB打开Room.build();

实际换数据库的时候,由于无法打开数据库,导致线程阻塞很久,最后解决方式是删除了原有的数据库,重新创建

使用 WCDB 其他功能

Room 使用了 SupportSQLiteDatabase 接口来提供底层操作的抽象,Room 所有相关的 API 返回的都是 SupportSQLiteDatabase 接口,如需要使用 WCDB 其他功能(比如 Repair)一般需要 SQLiteDatabase 接口,可以通过下面的方式取得。

// MyDatabase 为生成的 RoomDatabase
MyDatabase db = Room.databaseBuilder(...).openHelperFactory(new WCDBOpenHelperFactory(...)).build();// 用这个方法获取 SQLiteDatabase 接口
SQLiteDatabase sqlite = ((WCDBDatabase)db.getOpenHelper().getWritableDatabase()).getInnerDatabase();// 使用 sqlite

或者在初始化时设置 callback

MyDatabase db = Room.databaseBuilder(...).openHelperFactory(new WCDBOpenHelperFactory(...))// 添加初始化回调接口.addCallback(new RoomDatabase.Callback() {@Overridepublic void onCreate(@NonNull SupportSQLiteDatabase db) {// 从 SupportSQLiteDatabase 获取 SQLiteDatabaseSQLiteDatabase sqlite = ((WCDBDatabase)db).getInnerDatabase();// 做其他事}}).build();

上述功能暂时没用过

ROOM数据库使用

ROOM数据库中三个主要组成部分

1、Entity

@Entity
public class User {@PrimaryKeypublic int uid;@ColumnInfo(name = "first_name")public String firstName;//如果表中的name跟变量名不同,可以自行设置@ColumnInfo(name = "last_name")public String lastName;
}

2、Dao

@Dao
public interface UserDao {@Query("SELECT * FROM user")List<User> getAll();@Query("SELECT * FROM user WHERE uid IN (:userIds)")List<User> loadAllByIds(int[] userIds);@Query("SELECT * FROM user WHERE first_name LIKE :first AND " +"last_name LIKE :last LIMIT 1")User findByName(String first, String last);@Insertvoid insertAll(User... users);//@Deletevoid delete(User user);
}

3、DataBase

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {public abstract UserDao userDao();
}

创建数据库

AppDatabase db = Room.databaseBuilder(getApplicationContext(),AppDatabase.class, "database-name").build();

数据库的增删查改CRUD

1、Insert

@Dao
public interface MyDao {@Insert(onConflict = OnConflictStrategy.REPLACE)public void insertUsers(User... users);@Insertpublic void insertBothUsers(User user1, User user2);@Insertpublic void insertUsersAndFriends(User user, List<User> friends);
}

如果@INSERT方法只接收一个参数,它可以返回一个long,这是插入项的新rowId。如果参数是数组或集合,则应该返回long[]或list。

2、Update

@Dao
public interface MyDao {@Updatepublic void updateUsers(User... users);
}

可以让此方法返回一个int值,指示数据库中更新的行数。

3、Delete

@Dao
public interface MyDao {@Deletepublic void deleteUsers(User... users);
}

可以让此方法返回一个int值,指示从数据库中删除的行数。

4、Query

每个@Query方法都在编译时进行验证,因此如果查询有问题,则会发生编译错误,而不是运行时失败。
Room还验证查询的返回值,以便如果返回对象中的字段名称与查询响应中的相应列名不匹配,Room将通过以下两种方式之一提醒您:

  • 如果只有某些字段名匹配,则会发出警告。
  • 如果没有匹配的字段名,则会产生错误。
@Dao
public interface MyDao {@Query("SELECT * FROM user WHERE age > :minAge")public User[] loadAllUsersOlderThan(int minAge);
}

需要注意的是:当只需要查找类中的几列时:

  1. 需要使用@SupperssWarnings注解
  2. 对于不需要查找的列,其类型如果为基本数据类型,则需要转换为包装类,修改其get方法。如:
//原get方法
get int getLib_id(){return lib_id;
};
//将基本类型改为包装类
get Integer getLib_id(){
if(this.lib_id == null) return 0;return lib_id;
};

ps: 如果想要使用非实体类参数来增删改数据,也要使用@Query注解。
此外,还可以在sql语句中进行一些复杂的查询。

    @Query("delete from user  where lastName=:lastName")int deleteUserByLastName(String lastName);@Query("select * from user where age>:age")List<User> queryUsersByAge(int age);

@Query注解中可以使用复杂的SQL语句。Room内部封装了SQLite,Dao和Database文件会在\app\build\generated\ap_generated_sources\debug\out[package name]\database下生成对应的[XXXDao_impl.java]文件和[XXXDatabase_impl.java]文件。
其原理是,在生成的XXXDao_impl.java文件中,将注解内的SQL语句作为String提取出来,并使用RooSQLiteQuery进行解析,再使用Cursor取出要查询的数据。具体如下:

 @Overridepublic List<User> queryUsersByAge(final int age) {final String _sql = "select * from user where age>?";final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);int _argIndex = 1;_statement.bindLong(_argIndex, age);__db.assertNotSuspendingTransaction();final Cursor _cursor = DBUtil.query(__db, _statement, false, null);try {final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");final int _cursorIndexOfFirstName = CursorUtil.getColumnIndexOrThrow(_cursor, "firstName");final int _cursorIndexOfLastName = CursorUtil.getColumnIndexOrThrow(_cursor, "lastName");final int _cursorIndexOfAge = CursorUtil.getColumnIndexOrThrow(_cursor, "age");final List<User> _result = new ArrayList<User>(_cursor.getCount());while(_cursor.moveToNext()) {final User _item;_item = new User();_item.id = _cursor.getInt(_cursorIndexOfId);_item.firstName = _cursor.getString(_cursorIndexOfFirstName);_item.lastName = _cursor.getString(_cursorIndexOfLastName);_item.age = _cursor.getInt(_cursorIndexOfAge);_result.add(_item);}return _result;} finally {_cursor.close();_statement.release();}}

Room支持在编译时动态检查SQL语法。

数据库升级

当开发中使用了Google的Room框架的话,当你在之后的版本中新增了表或者改动了某些表结构的话,你就需要对数据库的版本号进行相应的更新,现在整理两种更新方式:

1. 简单粗暴作死型:

@Database(entities = {User.class}, version = 3)
public abstract class UsersDatabase extends RoomDatabase
database = Room.databaseBuilder(context.getApplicationContext(),UsersDatabase.class, "Sample.db")//添加下面这一行.fallbackToDestructiveMigration().build();

这种方式会清空数据库中的数据,所以要使用这种方式之前一定要慎重考虑。fallbackToDestructiveMigration会将所有表全部丢弃。

2. 正确姿势:

a) 修改数据库版本号

@Database(entities = {User.class}, version = 2)
public abstract class UsersDatabase extends RoomDatabase

b) 创建Migration,1和2分别代表上一个版本和新的版本

static final Migration MIGRATION_1_2 = new Migration(1, 2) {@Overridepublic void migrate(SupportSQLiteDatabase database) {//此处对于数据库中的所有更新都需要写下面的代码database.execSQL("ALTER TABLE users "+ " ADD COLUMN last_update INTEGER");}
};

c)把migration 添加到 Room database builder

database = Room.databaseBuilder(context.getApplicationContext(),UsersDatabase.class, "Sample.db")//增加下面这一行.addMigrations(MIGRATION_1_2).build();

注:SQLite的ALTER TABLE命令非常局限,只支持重命名表以及添加新的字段。

总结

使用WCDB结合ROOM数据库,可以大大减少代码量,但需要在注解中使用sql语句对数据库进行增删查改。使用过程中可能会遇到各种问题,这里总结一下我遇到的坑:

  • 运行时报错:

Android dependency ‘android.arch.core:runtime’ has different version for the compile (1.0.0) and runtime (1.1.1) classpath.

解决方法:

将implementation ‘com.tencent.wcdb:room:1.0.8’ 的implementation
改为 api ‘com.tencent.wcdb:room:1.0.8’

  • 如果只是build了数据库,但是没有操作的话,数据库是不会创建到本地的,如果在文件夹里没找到,大家不要方_(:з」∠)_
  • delete和insert操作,如果没有对应的数据可能会crash掉,建议使用之前先检查一下有没有数据。
  • 持续掉坑ing,再有什么情况会更新的~~~

Android使用WCDB+Room ORM相关推荐

  1. android 连接mysql orm_Android ORM框架 GreenDao 的使用详解

    一.前言 关于 Android 中常用的数据存储方式我们前面已经讲了 Sp 存储和文件存储,但是对于数据量比较大,并且结构复杂的数据我们想要存储只能通过数据库进行处理,Android 中提供了一个 S ...

  2. android微信wcdb,[资讯] 微信正式开源移动端数据库组件WCDB!

    对于iOS开发者来说,数据库的技术选型一直是个令人头痛的问题.由于Apple提供的CoreData框架差强人意,使得开发者们纷纷将目光投向开源社区,寻找更好的存储方案. 对于微信也是如此.数据库是微信 ...

  3. Wcdb android 目录,WCDB漫谈

    前言 移动端的数据库选型一直是一个难题,直到前段时间看到了WeMobileDev(微信前端团队)放出了第三个开源组件-WCDB WCDB(WeChat DataBase)是微信官方的移动端数据库组件, ...

  4. android微信wcdb,一篇文章get微信开源移动端数据库组件WCDB的一切!

    1.前言 微信团队已于2017年06月09日正式开源了微信自用的移动端数据库组件 WCDB(WeChat Database),详见<[资讯] 微信正式开源移动端数据库组件WCDB!>. W ...

  5. Wcdb android 目录,wcdb使用笔记

    本地数据加密 由于项目涉及到一些用户隐私数据的存储,所以需要对保存在客户端本地的数据进行加密,以防止用户隐私数据在设备被root的情况下出现泄漏.目前android的本地数据存储基本分为file,sh ...

  6. Android使用WCDB+Room 总结

    最近项目有需要用到wcdb数据库,并且保证和IOS互通数据,在网上找很多相关资料,最后还是靠自己一点点摸索成功,现在做个总结. 一.在gradle 里加上 WCDB 相关的 room 组件 def r ...

  7. Wcdb android 目录,介绍 - 《WCDB - 腾讯开源的移动数据库框架》 - 书栈网 · BookStack...

    WCDB 相关讨论可以加我们的QQ群WCDB 技术交流群: 190485752 WCDB iOS/macOS 群: 708134978 WCDB Android 群: 868268492 WCDB W ...

  8. [Android]Android端ORM框架——RapidORM(v1.0)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4748077.html  Android上主流的ORM框架有很多 ...

  9. Android 开源项目android-open-project工具库解析之(一) 依赖注入,图片缓存,网络相关,数据库orm工具包,Android公共库...

    一.依赖注入DI 通过依赖注入降低View.服务.资源简化初始化.事件绑定等反复繁琐工作 AndroidAnnotations(Code Diet) android高速开发框架 项目地址:https: ...

最新文章

  1. linux 安装 nodejs
  2. boost::math模块使用指定宽度的浮点 typedef估中等复杂的数学函数的测试程序
  3. linux 释放cache 内存
  4. Redis布隆过滤器
  5. copying mysql status_mysql慢查询copying to tmp table
  6. PHP:10个不常见却非常有用的PHP函数
  7. springmvc为什么不能拦截jsp页面?
  8. centos mysql 主从_Centos下MySQL主从同步配置
  9. markdown引入代码_markdown简单使用之插入代码段
  10. oracle数据库笔记---pl/sql的基础使用方法
  11. Eclipse如何新建TOMCAT并配置Server Locations和Publishing属性
  12. Linux音频驱动-声音采集过程
  13. C4996 'GetVersionExW': 被声明为已否决 TTS_one f:\vs2015\speechsdk\include\sphel
  14. 传奇私服服务器怎么增加npc,传奇添加NPC的方法以及形象代码计算
  15. 设计的银行账户管理系统,增加一个VIP账户的管理
  16. Poco C++类库使用说明
  17. eversync safari_Eversync:书签同步插件
  18. C语言简介之进制转换,原码、反码、补码,位运算符,函数
  19. 魔兽世界服务器同时在线人数,魔兽世界怀旧服国服同时在线人数达到60万,排队30万,即将破百万...
  20. Excel筛选之高级筛选篇

热门文章

  1. pplive网站存在存储型跨站脚本漏洞
  2. 中缀表达式求解——全网最详细教程
  3. 厦门大学计算机科学庄朝晖,庄朝晖-厦门大学信息学院 | 掌握信息,把握未来...
  4. EMIF接口时序和参考代码
  5. WIN7中AUTOCAD字体问题
  6. 使用govendor管理Golang项目依赖
  7. [软件人生]再论我会回答什么样的问题,帮助哪些人
  8. 通过电子邮件发送简历
  9. CV 领域的最美情话
  10. Adobe Audition生成正弦波