Jetpack系列-Room使用和源码分析
1 简介
Room是Google官方在SQLite基础上封装的一款数据持久库,是Jetpack全家桶的一员,和Jetpack其他库有着可以高度搭配协调的天然优势。Room使用APT技术,大大简化了使用SQLite的代码量,只需使用注解配合少量代码即可实现高效的数据库操作。
优点:
- Google官方库,和Jetpack其他库(比如Lifecycle,LiveData)等有天然的融合搭配使用优势。
- 在编译器可以对SQL语法进行检查。
- 使用APT,简单地几个注解搭配少量代码即可使用,大量减少模板代码。
- 查询代码自定义,可以实现更复杂的查询功能,也可以对SQL语句进行优化。
- 简化数据库的迁移路径。
不足:
- 查询时必须手动写SQL语句,不提供默认的查询配置。
- 效率比其他数据库框架(GreenDao等)并没有多少提高。
- 数据库版本升级稍显复杂。
Google官方文档:developer.android.com/jetpack/and…
2 主要组件
Room 包含三个主要组件:
-
DataBase:数据库类,用
@Database
标注,继承RoomDatabase,用于保存数据库并作为应用持久性数据底层连接的主要访问点。 -
Entity:数据实体,用
@Entity
标注,用于表示应用的数据库中的表。 -
Data Access Object:数据访问对象 (DAO),用
@DAO
标注,提供您的应用可用于查询、更新、插入和删除数据库中的数据的方法。
在DataBase中获取DAO,然后在业务层使用DAO去进行数据的操作。
3 单独使用Room
在Module的build.gradle下添加APT支持。
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
在Module的build.gradle下引入依赖。
def room_version = "2.4.2"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
创建数据实体Book,包含bookId,name,author,price4个字段,由于bookId被设为主键,需要自增长,所以构造方法里不能有bookId。
@Entity
标注Book,就表示在数据库中创建了一个名为“Book”的表。
@PrimaryKey
设置该字段是主键,autoGenerate = true表示主键自增长,bookId会从1开始,每插入一条数据就会+1.
@ColumnInfo
设置该字段在数据库中的列名,name后的值就是在数据库中的列名。@ColumnInfo
可选,不添加的话数据库列名和实体字段名一致。
@Entity
class Book(
var name: String,
@field:ColumnInfo(name = "author") var author: String,
@field:ColumnInfo(name = "price") var price: Float
) {
@PrimaryKey(autoGenerate = true)
var bookId = 0
override fun toString(): String {
return "Book(name='$name', author='$author', price=$price, bookId=$bookId)"
}
}
接着创建一个接口类DAO,在DAO中定义数据库操作方法。用@Dao
来标注,然后定义接口方法操作数据库,用对应的注解标注,增删改查分别对应@Insert
、 @Delete
、 @Update
、@Query
。
@Dao
interface BookDao {
@Insert
fun insert(book: Book)
@Delete
fun delete(book: Book)
@Update
fun update(book: Book)
//根据名字查数据
@Query("select * from Book where name like:name")
fun queryBookByName(name: String): MutableList<Book>
//根据一组id查数据
@Query("select * from Book where bookId in(:bookIds)")
fun queryBookByIds(bookIds: Array<Int>): MutableList<Book>
//查询所有数据
@Query("select * from Book")
fun queryAllBook(): MutableList<Book>
//查询所有数据中的name和author
@Query("select name,author from Book")
fun queryBookWithPartFiled(): MutableList<Book2>
}
然后创建DataBase,继承RoomDatabase,用注解@Database
标注,entities后的值表示数据库中的实体,也就是表,可以有多个,version是数据库版本,exportSchema表示是否支持导出,如果没有指定数据库导出路径,需要设置为false,不然会报错。数据库导出请看文档:developer.android.com/jetpack/and…。
DataBase中提供了一个方法获取DAO。
@Database(entities = [Book::class], version = 1, exportSchema = false)
abstract class AppDataBase : RoomDatabase() {
abstract fun bookDao(): BookDao
}
最后在Activity初始化数据库并使用。数据库初始化方法是Room.databaseBuilder(Context context, Class<T> klass, String name)
,3个参数分别是上下文,DataBase类,数据库名称。
class MainActivity : AppCompatActivity() {
private val TAG = "---MS---"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Room默认需要在子线程使用
thread {
val database =
Room.databaseBuilder(applicationContext, AppDataBase::class.java, "MsDB")
// .allowMainThreadQueries()//如果需要在主线程中使用,可以开启这行代码
.build()
val dao = database.bookDao()
//插入4条数据
dao.insert(Book("三体", "刘慈欣", 55.6f))
dao.insert(Book("黄金时代", "王小波", 32.9f))
dao.insert(Book("生死疲劳", "莫言", 32.9f))
dao.insert(Book("一句顶一万句", "刘震云", 32.9f))
Log.d(TAG, "查询名字为三体发的数据: ${dao.queryBookByName("三体")}")
Log.d(TAG, "查询id为1,3,4的数据: ${dao.queryBookByIds(arrayOf(1, 3, 4))}")
Log.d(TAG, "查询所有数据: ${dao.queryAllBook()}")
Log.d(TAG, "查询name和author: ${dao.queryBookWithPartFiled()}")
}
}
}
回到BookDao中可以看到,queryBookWithPartFiled
方法查询的不是Book表中所有列,而是name和author这两列,返回的对象是Book2,不是Book。这是因为Room查询的时候,查询的列必须和返回的实体中所有字段对应,这也是Room的一个弊端之一。所以这里又定义了一个Book2,用来接收查询到的数据,Book2中只有两个字段name和author,并且不能用@Entity标注,不然Book2也变成了数据库中的一张表。
class Book2(
var name: String,
@field:ColumnInfo(name = "author") var author: String,
) {
override fun toString(): String {
return "Book2(name='$name', author='$author')"
}
}
4 数据库版本升级
Room的数据库版本升级稍显麻烦,核心是Migration类。
修改实体类,新增一个publishData字段。
@Entity
class Book(
var name: String,
@field:ColumnInfo(name = "author") var author: String,
@field:ColumnInfo(name = "price") var price: Float,
//新增字段
@field:ColumnInfo(name = "data") var publishData: String
) {
@PrimaryKey(autoGenerate = true)
var bookId = 0
override fun toString(): String {
return "Book(name='$name', author='$author', price=$price, bookId=$bookId)"
}
}
然后把version改为2。
@Database(entities = [Book::class], version = 2, exportSchema = false)
abstract class AppDataBase : RoomDatabase() {
abstract fun bookDao(): BookDao
}
定义一个内部类,继承Migration
,实现migrate
方法,执行语句往表中添加列。
/**
* 从版本1升级到版本2
*/
inner class Migration1To2 : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
//执行sql语句,添加data列
database.execSQL("alter table book add column data TEXT not null default '2020-05-01' ")
}
}
最后在Room初始化的时候添加.addMigrations(Migration1To2())
。
val database =
Room.databaseBuilder(applicationContext, AppDataBase::class.java, "MsDB")
// .allowMainThreadQueries()//如果需要在主线程中使用,可以开启这行代码
//升级
.addMigrations(Migration1To2())
.build()
5 源码分析
Room使用APT技术,提供了大量的注解。
当用@Dao
标注BookDao类,会在build/generated/source/kapt/debug/包名/下生成BookDao_impl.java
。该类实现了BookDao中所有的接口方法,实现了具体的增删改查方法。
package cn.zhangmushui.room;
import android.database.Cursor;
import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.EntityInsertionAdapter;
import androidx.room.RoomDatabase;
import androidx.room.RoomSQLiteQuery;
import androidx.room.util.CursorUtil;
import androidx.room.util.DBUtil;
import androidx.room.util.StringUtil;
import androidx.sqlite.db.SupportSQLiteStatement;
import java.lang.Class;
import java.lang.Integer;
import java.lang.Override;
import java.lang.String;
import java.lang.StringBuilder;
import java.lang.SuppressWarnings;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@SuppressWarnings({"unchecked", "deprecation"})
public final class BookDao_Impl implements BookDao {
private final RoomDatabase __db;
private final EntityInsertionAdapter<Book> __insertionAdapterOfBook;
private final EntityDeletionOrUpdateAdapter<Book> __deletionAdapterOfBook;
private final EntityDeletionOrUpdateAdapter<Book> __updateAdapterOfBook;
public BookDao_Impl(RoomDatabase __db) {
this.__db = __db;
this.__insertionAdapterOfBook = new EntityInsertionAdapter<Book>(__db) {
@Override
public String createQuery() {
return "INSERT OR ABORT INTO `Book` (`name`,`author`,`price`,`data`,`bookId`) VALUES (?,?,?,?,nullif(?, 0))";
}
@Override
public void bind(SupportSQLiteStatement stmt, Book value) {
if (value.getName() == null) {
stmt.bindNull(1);
} else {
stmt.bindString(1, value.getName());
}
if (value.getAuthor() == null) {
stmt.bindNull(2);
} else {
stmt.bindString(2, value.getAuthor());
}
stmt.bindDouble(3, value.getPrice());
if (value.getPublishData() == null) {
stmt.bindNull(4);
} else {
stmt.bindString(4, value.getPublishData());
}
stmt.bindLong(5, value.getBookId());
}
};
this.__deletionAdapterOfBook = new EntityDeletionOrUpdateAdapter<Book>(__db) {
@Override
public String createQuery() {
return "DELETE FROM `Book` WHERE `bookId` = ?";
}
@Override
public void bind(SupportSQLiteStatement stmt, Book value) {
stmt.bindLong(1, value.getBookId());
}
};
this.__updateAdapterOfBook = new EntityDeletionOrUpdateAdapter<Book>(__db) {
@Override
public String createQuery() {
return "UPDATE OR ABORT `Book` SET `name` = ?,`author` = ?,`price` = ?,`data` = ?,`bookId` = ? WHERE `bookId` = ?";
}
@Override
public void bind(SupportSQLiteStatement stmt, Book value) {
if (value.getName() == null) {
stmt.bindNull(1);
} else {
stmt.bindString(1, value.getName());
}
if (value.getAuthor() == null) {
stmt.bindNull(2);
} else {
stmt.bindString(2, value.getAuthor());
}
stmt.bindDouble(3, value.getPrice());
if (value.getPublishData() == null) {
stmt.bindNull(4);
} else {
stmt.bindString(4, value.getPublishData());
}
stmt.bindLong(5, value.getBookId());
stmt.bindLong(6, value.getBookId());
}
};
}
@Override
public void insert(final Book book) {
__db.assertNotSuspendingTransaction();
__db.beginTransaction();
try {
__insertionAdapterOfBook.insert(book);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
@Override
public void delete(final Book book) {
__db.assertNotSuspendingTransaction();
__db.beginTransaction();
try {
__deletionAdapterOfBook.handle(book);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
@Override
public void update(final Book book) {
__db.assertNotSuspendingTransaction();
__db.beginTransaction();
try {
__updateAdapterOfBook.handle(book);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
@Override
public List<Book> queryBookByName(final String name) {
final String _sql = "select * from Book where name like?";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
int _argIndex = 1;
if (name == null) {
_statement.bindNull(_argIndex);
} else {
_statement.bindString(_argIndex, name);
}
__db.assertNotSuspendingTransaction();
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");
final int _cursorIndexOfAuthor = CursorUtil.getColumnIndexOrThrow(_cursor, "author");
final int _cursorIndexOfPrice = CursorUtil.getColumnIndexOrThrow(_cursor, "price");
final int _cursorIndexOfPublishData = CursorUtil.getColumnIndexOrThrow(_cursor, "data");
final int _cursorIndexOfBookId = CursorUtil.getColumnIndexOrThrow(_cursor, "bookId");
final List<Book> _result = new ArrayList<Book>(_cursor.getCount());
while(_cursor.moveToNext()) {
final Book _item;
final String _tmpName;
if (_cursor.isNull(_cursorIndexOfName)) {
_tmpName = null;
} else {
_tmpName = _cursor.getString(_cursorIndexOfName);
}
final String _tmpAuthor;
if (_cursor.isNull(_cursorIndexOfAuthor)) {
_tmpAuthor = null;
} else {
_tmpAuthor = _cursor.getString(_cursorIndexOfAuthor);
}
final float _tmpPrice;
_tmpPrice = _cursor.getFloat(_cursorIndexOfPrice);
final String _tmpPublishData;
if (_cursor.isNull(_cursorIndexOfPublishData)) {
_tmpPublishData = null;
} else {
_tmpPublishData = _cursor.getString(_cursorIndexOfPublishData);
}
_item = new Book(_tmpName,_tmpAuthor,_tmpPrice,_tmpPublishData);
final int _tmpBookId;
_tmpBookId = _cursor.getInt(_cursorIndexOfBookId);
_item.setBookId(_tmpBookId);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
_statement.release();
}
}
@Override
public List<Book> queryBookByIds(final Integer[] bookIds) {
StringBuilder _stringBuilder = StringUtil.newStringBuilder();
_stringBuilder.append("select * from Book where bookId in(");
final int _inputSize = bookIds.length;
StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
_stringBuilder.append(")");
final String _sql = _stringBuilder.toString();
final int _argCount = 0 + _inputSize;
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, _argCount);
int _argIndex = 1;
for (Integer _item : bookIds) {
if (_item == null) {
_statement.bindNull(_argIndex);
} else {
_statement.bindLong(_argIndex, _item);
}
_argIndex ++;
}
__db.assertNotSuspendingTransaction();
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");
final int _cursorIndexOfAuthor = CursorUtil.getColumnIndexOrThrow(_cursor, "author");
final int _cursorIndexOfPrice = CursorUtil.getColumnIndexOrThrow(_cursor, "price");
final int _cursorIndexOfPublishData = CursorUtil.getColumnIndexOrThrow(_cursor, "data");
final int _cursorIndexOfBookId = CursorUtil.getColumnIndexOrThrow(_cursor, "bookId");
final List<Book> _result = new ArrayList<Book>(_cursor.getCount());
while(_cursor.moveToNext()) {
final Book _item_1;
final String _tmpName;
if (_cursor.isNull(_cursorIndexOfName)) {
_tmpName = null;
} else {
_tmpName = _cursor.getString(_cursorIndexOfName);
}
final String _tmpAuthor;
if (_cursor.isNull(_cursorIndexOfAuthor)) {
_tmpAuthor = null;
} else {
_tmpAuthor = _cursor.getString(_cursorIndexOfAuthor);
}
final float _tmpPrice;
_tmpPrice = _cursor.getFloat(_cursorIndexOfPrice);
final String _tmpPublishData;
if (_cursor.isNull(_cursorIndexOfPublishData)) {
_tmpPublishData = null;
} else {
_tmpPublishData = _cursor.getString(_cursorIndexOfPublishData);
}
_item_1 = new Book(_tmpName,_tmpAuthor,_tmpPrice,_tmpPublishData);
final int _tmpBookId;
_tmpBookId = _cursor.getInt(_cursorIndexOfBookId);
_item_1.setBookId(_tmpBookId);
_result.add(_item_1);
}
return _result;
} finally {
_cursor.close();
_statement.release();
}
}
@Override
public List<Book> queryAllBook() {
final String _sql = "select * from Book";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
__db.assertNotSuspendingTransaction();
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");
final int _cursorIndexOfAuthor = CursorUtil.getColumnIndexOrThrow(_cursor, "author");
final int _cursorIndexOfPrice = CursorUtil.getColumnIndexOrThrow(_cursor, "price");
final int _cursorIndexOfPublishData = CursorUtil.getColumnIndexOrThrow(_cursor, "data");
final int _cursorIndexOfBookId = CursorUtil.getColumnIndexOrThrow(_cursor, "bookId");
final List<Book> _result = new ArrayList<Book>(_cursor.getCount());
while(_cursor.moveToNext()) {
final Book _item;
final String _tmpName;
if (_cursor.isNull(_cursorIndexOfName)) {
_tmpName = null;
} else {
_tmpName = _cursor.getString(_cursorIndexOfName);
}
final String _tmpAuthor;
if (_cursor.isNull(_cursorIndexOfAuthor)) {
_tmpAuthor = null;
} else {
_tmpAuthor = _cursor.getString(_cursorIndexOfAuthor);
}
final float _tmpPrice;
_tmpPrice = _cursor.getFloat(_cursorIndexOfPrice);
final String _tmpPublishData;
if (_cursor.isNull(_cursorIndexOfPublishData)) {
_tmpPublishData = null;
} else {
_tmpPublishData = _cursor.getString(_cursorIndexOfPublishData);
}
_item = new Book(_tmpName,_tmpAuthor,_tmpPrice,_tmpPublishData);
final int _tmpBookId;
_tmpBookId = _cursor.getInt(_cursorIndexOfBookId);
_item.setBookId(_tmpBookId);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
_statement.release();
}
}
@Override
public List<Book2> queryBookWithPartFiled() {
final String _sql = "select name,author from Book";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
__db.assertNotSuspendingTransaction();
final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
try {
final int _cursorIndexOfName = 0;
final int _cursorIndexOfAuthor = 1;
final List<Book2> _result = new ArrayList<Book2>(_cursor.getCount());
while(_cursor.moveToNext()) {
final Book2 _item;
final String _tmpName;
if (_cursor.isNull(_cursorIndexOfName)) {
_tmpName = null;
} else {
_tmpName = _cursor.getString(_cursorIndexOfName);
}
final String _tmpAuthor;
if (_cursor.isNull(_cursorIndexOfAuthor)) {
_tmpAuthor = null;
} else {
_tmpAuthor = _cursor.getString(_cursorIndexOfAuthor);
}
_item = new Book2(_tmpName,_tmpAuthor);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
_statement.release();
}
}
public static List<Class<?>> getRequiredConverters() {
return Collections.emptyList();
}
}
当用@DataBase
标注AppDataBase类,会在build/generated/source/kapt/debug/包名/下生成AppDataBase_impl.java
。该类主要进行了表的创建工作。
package cn.zhangmushui.room;
import androidx.annotation.NonNull;
import androidx.room.DatabaseConfiguration;
import androidx.room.InvalidationTracker;
import androidx.room.RoomOpenHelper;
import androidx.room.RoomOpenHelper.Delegate;
import androidx.room.RoomOpenHelper.ValidationResult;
import androidx.room.migration.AutoMigrationSpec;
import androidx.room.migration.Migration;
import androidx.room.util.DBUtil;
import androidx.room.util.TableInfo;
import androidx.room.util.TableInfo.Column;
import androidx.room.util.TableInfo.ForeignKey;
import androidx.room.util.TableInfo.Index;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
import androidx.sqlite.db.SupportSQLiteOpenHelper.Callback;
import androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration;
import java.lang.Class;
import java.lang.Override;
import java.lang.String;
import java.lang.SuppressWarnings;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@SuppressWarnings({"unchecked", "deprecation"})
public final class AppDataBase_Impl extends AppDataBase {
private volatile BookDao _bookDao;
@Override
protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(2) {
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `Book` (`name` TEXT NOT NULL, `author` TEXT NOT NULL, `price` REAL NOT NULL, `data` TEXT NOT NULL, `bookId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '049deb639df8f34cc670d599e5105986')");
}
@Override
public void dropAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("DROP TABLE IF EXISTS `Book`");
if (mCallbacks != null) {
for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
mCallbacks.get(_i).onDestructiveMigration(_db);
}
}
}
@Override
protected void onCreate(SupportSQLiteDatabase _db) {
if (mCallbacks != null) {
for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
mCallbacks.get(_i).onCreate(_db);
}
}
}
@Override
public void onOpen(SupportSQLiteDatabase _db) {
mDatabase = _db;
internalInitInvalidationTracker(_db);
if (mCallbacks != null) {
for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
mCallbacks.get(_i).onOpen(_db);
}
}
}
@Override
public void onPreMigrate(SupportSQLiteDatabase _db) {
DBUtil.dropFtsSyncTriggers(_db);
}
@Override
public void onPostMigrate(SupportSQLiteDatabase _db) {
}
@Override
protected RoomOpenHelper.ValidationResult onValidateSchema(SupportSQLiteDatabase _db) {
final HashMap<String, TableInfo.Column> _columnsBook = new HashMap<String, TableInfo.Column>(5);
_columnsBook.put("name", new TableInfo.Column("name", "TEXT", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
_columnsBook.put("author", new TableInfo.Column("author", "TEXT", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
_columnsBook.put("price", new TableInfo.Column("price", "REAL", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
_columnsBook.put("data", new TableInfo.Column("data", "TEXT", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
_columnsBook.put("bookId", new TableInfo.Column("bookId", "INTEGER", true, 1, null, TableInfo.CREATED_FROM_ENTITY));
final HashSet<TableInfo.ForeignKey> _foreignKeysBook = new HashSet<TableInfo.ForeignKey>(0);
final HashSet<TableInfo.Index> _indicesBook = new HashSet<TableInfo.Index>(0);
final TableInfo _infoBook = new TableInfo("Book", _columnsBook, _foreignKeysBook, _indicesBook);
final TableInfo _existingBook = TableInfo.read(_db, "Book");
if (! _infoBook.equals(_existingBook)) {
return new RoomOpenHelper.ValidationResult(false, "Book(cn.zhangmushui.room.Book).\n"
+ " Expected:\n" + _infoBook + "\n"
+ " Found:\n" + _existingBook);
}
return new RoomOpenHelper.ValidationResult(true, null);
}
}, "049deb639df8f34cc670d599e5105986", "4598151ad10511f4531db7d976d441f6");
final SupportSQLiteOpenHelper.Configuration _sqliteConfig = SupportSQLiteOpenHelper.Configuration.builder(configuration.context)
.name(configuration.name)
.callback(_openCallback)
.build();
final SupportSQLiteOpenHelper _helper = configuration.sqliteOpenHelperFactory.create(_sqliteConfig);
return _helper;
}
@Override
protected InvalidationTracker createInvalidationTracker() {
final HashMap<String, String> _shadowTablesMap = new HashMap<String, String>(0);
HashMap<String, Set<String>> _viewTables = new HashMap<String, Set<String>>(0);
return new InvalidationTracker(this, _shadowTablesMap, _viewTables, "Book");
}
@Override
public void clearAllTables() {
super.assertNotMainThread();
final SupportSQLiteDatabase _db = super.getOpenHelper().getWritableDatabase();
try {
super.beginTransaction();
_db.execSQL("DELETE FROM `Book`");
super.setTransactionSuccessful();
} finally {
super.endTransaction();
_db.query("PRAGMA wal_checkpoint(FULL)").close();
if (!_db.inTransaction()) {
_db.execSQL("VACUUM");
}
}
}
@Override
protected Map<Class<?>, List<Class<?>>> getRequiredTypeConverters() {
final HashMap<Class<?>, List<Class<?>>> _typeConvertersMap = new HashMap<Class<?>, List<Class<?>>>();
_typeConvertersMap.put(BookDao.class, BookDao_Impl.getRequiredConverters());
return _typeConvertersMap;
}
@Override
public Set<Class<? extends AutoMigrationSpec>> getRequiredAutoMigrationSpecs() {
final HashSet<Class<? extends AutoMigrationSpec>> _autoMigrationSpecsSet = new HashSet<Class<? extends AutoMigrationSpec>>();
return _autoMigrationSpecsSet;
}
@Override
public List<Migration> getAutoMigrations(
@NonNull Map<Class<? extends AutoMigrationSpec>, AutoMigrationSpec> autoMigrationSpecsMap) {
return Arrays.asList();
}
@Override
public BookDao bookDao() {
if (_bookDao != null) {
return _bookDao;
} else {
synchronized(this) {
if(_bookDao == null) {
_bookDao = new BookDao_Impl(this);
}
return _bookDao;
}
}
}
}