Jetpack系列-Room使用和源码分析

1 简介

Room是Google官方在SQLite基础上封装的一款数据持久库,是Jetpack全家桶的一员,和Jetpack其他库有着可以高度搭配协调的天然优势。Room使用APT技术,大大简化了使用SQLite的代码量,只需使用注解配合少量代码即可实现高效的数据库操作。

优点:

  • Google官方库,和Jetpack其他库(比如Lifecycle,LiveData)等有天然的融合搭配使用优势。
  • 在编译器可以对SQL语法进行检查。
  • 使用APT,简单地几个注解搭配少量代码即可使用,大量减少模板代码。
  • 查询代码自定义,可以实现更复杂的查询功能,也可以对SQL语句进行优化。
  • 简化数据库的迁移路径。

不足:

  • 查询时必须手动写SQL语句,不提供默认的查询配置。
  • 效率比其他数据库框架(GreenDao等)并没有多少提高。
  • 数据库版本升级稍显复杂。

Google官方文档:https://developer.android.com/jetpack/androidx/releases/room

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

    //根据一组id查数据
    @Query("select * from Book where bookId in(:bookIds)")
    fun queryBookByIds(bookIds: Array): MutableList

    //查询所有数据
    @Query("select * from Book")
    fun queryAllBook(): MutableList

    //查询所有数据中的name和author
    @Query("select name,author from Book")
    fun queryBookWithPartFiled(): MutableList
    
}

然后创建DataBase,继承RoomDatabase,用注解@Database标注,entities后的值表示数据库中的实体,也就是表,可以有多个,version是数据库版本,exportSchema表示是否支持导出,如果没有指定数据库导出路径,需要设置为false,不然会报错。数据库导出请看文档:https://developer.android.com/jetpack/androidx/releases/room#compiler-options。

DataBase中提供了一个方法获取DAO。

@Database(entities = [Book::class], version = 1, exportSchema = false)
abstract class AppDataBase : RoomDatabase() {
    abstract fun bookDao(): BookDao
}

最后在Activity初始化数据库并使用。数据库初始化方法是Room.databaseBuilder(Context context, Class 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 __insertionAdapterOfBook;
    
    private final EntityDeletionOrUpdateAdapter __deletionAdapterOfBook;
    
    private final EntityDeletionOrUpdateAdapter __updateAdapterOfBook;
    
    public BookDao_Impl(RoomDatabase __db) {
        this.__db = __db;
        this.__insertionAdapterOfBook = new EntityInsertionAdapter(__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(__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(__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 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 _result = new ArrayList(_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 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 _result = new ArrayList(_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 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 _result = new ArrayList(_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 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 _result = new ArrayList(_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> 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 _columnsBook = new HashMap(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 _foreignKeysBook = new HashSet(0);
        final HashSet _indicesBook = new HashSet(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 _shadowTablesMap = new HashMap(0);
    HashMap> _viewTables = new HashMap>(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, List>> getRequiredTypeConverters() {
    final HashMap, List>> _typeConvertersMap = new HashMap, List>>();
    _typeConvertersMap.put(BookDao.class, BookDao_Impl.getRequiredConverters());
    return _typeConvertersMap;
  }

  @Override
  public Set> getRequiredAutoMigrationSpecs() {
    final HashSet> _autoMigrationSpecsSet = new HashSet>();
    return _autoMigrationSpecsSet;
  }

  @Override
  public List getAutoMigrations(
      @NonNull Map, 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;
      }
    }
  }
}
阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/19440,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?