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

1 簡(jiǎn)介

Room是Google官方在SQLite基礎(chǔ)上封裝的一款數(shù)據(jù)持久庫(kù),是Jetpack全家桶的一員,和Jetpack其他庫(kù)有著可以高度搭配協(xié)調(diào)的天然優(yōu)勢(shì)。Room使用APT技術(shù),大大簡(jiǎn)化了使用SQLite的代碼量鸭廷,只需使用注解配合少量代碼即可實(shí)現(xiàn)高效的數(shù)據(jù)庫(kù)操作。

優(yōu)點(diǎn):

  • Google官方庫(kù)潜必,和Jetpack其他庫(kù)(比如Lifecycle靴姿,LiveData)等有天然的融合搭配使用優(yōu)勢(shì)。
  • 在編譯器可以對(duì)SQL語(yǔ)法進(jìn)行檢查磁滚。
  • 使用APT,簡(jiǎn)單地幾個(gè)注解搭配少量代碼即可使用,大量減少模板代碼垂攘。
  • 查詢代碼自定義维雇,可以實(shí)現(xiàn)更復(fù)雜的查詢功能,也可以對(duì)SQL語(yǔ)句進(jìn)行優(yōu)化晒他。
  • 簡(jiǎn)化數(shù)據(jù)庫(kù)的遷移路徑吱型。

不足:

  • 查詢時(shí)必須手動(dòng)寫(xiě)SQL語(yǔ)句,不提供默認(rèn)的查詢配置陨仅。
  • 效率比其他數(shù)據(jù)庫(kù)框架(GreenDao等)并沒(méi)有多少提高津滞。
  • 數(shù)據(jù)庫(kù)版本升級(jí)稍顯復(fù)雜。

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

2 主要組件

Room 包含三個(gè)主要組件:

  • DataBase:數(shù)據(jù)庫(kù)類(lèi)灼伤,用@Database標(biāo)注触徐,繼承RoomDatabase,用于保存數(shù)據(jù)庫(kù)并作為應(yīng)用持久性數(shù)據(jù)底層連接的主要訪問(wèn)點(diǎn)狐赡。
  • Entity:數(shù)據(jù)實(shí)體撞鹉,用@Entity標(biāo)注,用于表示應(yīng)用的數(shù)據(jù)庫(kù)中的表颖侄。
  • Data Access Object:數(shù)據(jù)訪問(wèn)對(duì)象 (DAO)鸟雏,用@DAO標(biāo)注,提供您的應(yīng)用可用于查詢览祖、更新孝鹊、插入和刪除數(shù)據(jù)庫(kù)中的數(shù)據(jù)的方法。

在DataBase中獲取DAO展蒂,然后在業(yè)務(wù)層使用DAO去進(jìn)行數(shù)據(jù)的操作惶室。

3 單獨(dú)使用Room

在Module的build.gradle下添加APT支持。

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'
}

在Module的build.gradle下引入依賴(lài)玄货。

def room_version = "2.4.2"

implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

創(chuàng)建數(shù)據(jù)實(shí)體Book皇钞,包含bookId,name松捉,author夹界,price4個(gè)字段,由于bookId被設(shè)為主鍵隘世,需要自增長(zhǎng)可柿,所以構(gòu)造方法里不能有bookId。

@Entity標(biāo)注Book丙者,就表示在數(shù)據(jù)庫(kù)中創(chuàng)建了一個(gè)名為“Book”的表复斥。

@PrimaryKey設(shè)置該字段是主鍵,autoGenerate = true表示主鍵自增長(zhǎng)械媒,bookId會(huì)從1開(kāi)始目锭,每插入一條數(shù)據(jù)就會(huì)+1.

@ColumnInfo設(shè)置該字段在數(shù)據(jù)庫(kù)中的列名评汰,name后的值就是在數(shù)據(jù)庫(kù)中的列名。@ColumnInfo可選痢虹,不添加的話數(shù)據(jù)庫(kù)列名和實(shí)體字段名一致被去。

@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)"
    }
}

接著創(chuàng)建一個(gè)接口類(lèi)DAO,在DAO中定義數(shù)據(jù)庫(kù)操作方法奖唯。用@Dao來(lái)標(biāo)注惨缆,然后定義接口方法操作數(shù)據(jù)庫(kù),用對(duì)應(yīng)的注解標(biāo)注丰捷,增刪改查分別對(duì)應(yīng)@Insert坯墨、 @Delete@Update病往、@Query捣染。

@Dao
interface BookDao {

    @Insert
    fun insert(book: Book)

    @Delete
    fun delete(book: Book)

    @Update
    fun update(book: Book)

    //根據(jù)名字查數(shù)據(jù)
    @Query("select * from Book where name like:name")
    fun queryBookByName(name: String): MutableList<Book>

    //根據(jù)一組id查數(shù)據(jù)
    @Query("select * from Book where bookId in(:bookIds)")
    fun queryBookByIds(bookIds: Array<Int>): MutableList<Book>

    //查詢所有數(shù)據(jù)
    @Query("select * from Book")
    fun queryAllBook(): MutableList<Book>

    //查詢所有數(shù)據(jù)中的name和author
    @Query("select name,author from Book")
    fun queryBookWithPartFiled(): MutableList<Book2>
    
}

然后創(chuàng)建DataBase,繼承RoomDatabase荣恐,用注解@Database標(biāo)注液斜,entities后的值表示數(shù)據(jù)庫(kù)中的實(shí)體,也就是表叠穆,可以有多個(gè)少漆,version是數(shù)據(jù)庫(kù)版本,exportSchema表示是否支持導(dǎo)出硼被,如果沒(méi)有指定數(shù)據(jù)庫(kù)導(dǎo)出路徑示损,需要設(shè)置為false,不然會(huì)報(bào)錯(cuò)嚷硫。數(shù)據(jù)庫(kù)導(dǎo)出請(qǐng)看文檔:https://developer.android.com/jetpack/androidx/releases/room#compiler-options检访。

DataBase中提供了一個(gè)方法獲取DAO。

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

最后在Activity初始化數(shù)據(jù)庫(kù)并使用仔掸。數(shù)據(jù)庫(kù)初始化方法是Room.databaseBuilder(Context context, Class<T> klass, String name)脆贵,3個(gè)參數(shù)分別是上下文,DataBase類(lèi)起暮,數(shù)據(jù)庫(kù)名稱(chēng)卖氨。

class MainActivity : AppCompatActivity() {
    
    private val TAG = "---MS---"
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        //Room默認(rèn)需要在子線程使用
        thread {
            val database =
            Room.databaseBuilder(applicationContext, AppDataBase::class.java, "MsDB")
            //                    .allowMainThreadQueries()//如果需要在主線程中使用,可以開(kāi)啟這行代碼
                .build()
            val dao = database.bookDao()
            
            //插入4條數(shù)據(jù)
            dao.insert(Book("三體", "劉慈欣", 55.6f))
            dao.insert(Book("黃金時(shí)代", "王小波", 32.9f))
            dao.insert(Book("生死疲勞", "莫言", 32.9f))
            dao.insert(Book("一句頂一萬(wàn)句", "劉震云", 32.9f))
            
            Log.d(TAG, "查詢名字為三體發(fā)的數(shù)據(jù): ${dao.queryBookByName("三體")}")
            Log.d(TAG, "查詢id為1负懦,3筒捺,4的數(shù)據(jù): ${dao.queryBookByIds(arrayOf(1, 3, 4))}")
            Log.d(TAG, "查詢所有數(shù)據(jù): ${dao.queryAllBook()}")
            Log.d(TAG, "查詢name和author: ${dao.queryBookWithPartFiled()}")
            
        }
    }
}

回到BookDao中可以看到,queryBookWithPartFiled方法查詢的不是Book表中所有列纸厉,而是name和author這兩列系吭,返回的對(duì)象是Book2,不是Book颗品。這是因?yàn)镽oom查詢的時(shí)候肯尺,查詢的列必須和返回的實(shí)體中所有字段對(duì)應(yīng)沃缘,這也是Room的一個(gè)弊端之一。所以這里又定義了一個(gè)Book2蟆盹,用來(lái)接收查詢到的數(shù)據(jù)孩灯,Book2中只有兩個(gè)字段name和author闺金,并且不能用@Entity標(biāo)注逾滥,不然Book2也變成了數(shù)據(jù)庫(kù)中的一張表。

class Book2(
    var name: String,
    @field:ColumnInfo(name = "author") var author: String,
) {
    override fun toString(): String {
        return "Book2(name='$name', author='$author')"
    }
}

4 數(shù)據(jù)庫(kù)版本升級(jí)

Room的數(shù)據(jù)庫(kù)版本升級(jí)稍顯麻煩败匹,核心是Migration類(lèi)寨昙。

修改實(shí)體類(lèi),新增一個(gè)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
}

定義一個(gè)內(nèi)部類(lèi),繼承Migration槽棍,實(shí)現(xiàn)migrate方法捉蚤,執(zhí)行語(yǔ)句往表中添加列。

/**
* 從版本1升級(jí)到版本2
*/
inner class Migration1To2 : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        //執(zhí)行sql語(yǔ)句炼七,添加data列
        database.execSQL("alter table book add column data TEXT not null default '2020-05-01' ")
    }
}

最后在Room初始化的時(shí)候添加.addMigrations(Migration1To2())缆巧。

val database =
    Room.databaseBuilder(applicationContext, AppDataBase::class.java, "MsDB")
//                    .allowMainThreadQueries()//如果需要在主線程中使用,可以開(kāi)啟這行代碼
    //升級(jí)
    .addMigrations(Migration1To2())
                    .build()

5 源碼分析

Room使用APT技術(shù)豌拙,提供了大量的注解陕悬。

當(dāng)用@Dao標(biāo)注BookDao類(lèi),會(huì)在build/generated/source/kapt/debug/包名/下生成BookDao_impl.java按傅。該類(lèi)實(shí)現(xiàn)了BookDao中所有的接口方法捉超,實(shí)現(xiàn)了具體的增刪改查方法。

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();
    }
}

當(dāng)用@DataBase標(biāo)注AppDataBase類(lèi)唯绍,會(huì)在build/generated/source/kapt/debug/包名/下生成AppDataBase_impl.java拼岳。該類(lèi)主要進(jìn)行了表的創(chuàng)建工作。

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;
      }
    }
  }
}

關(guān)注木水小站 (zhangmushui.cn)和微信公眾號(hào)【木水Code】况芒,及時(shí)獲取更多最新技術(shù)干貨惜纸。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市牛柒,隨后出現(xiàn)的幾起案子堪簿,更是在濱河造成了極大的恐慌,老刑警劉巖皮壁,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件椭更,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蛾魄,警方通過(guò)查閱死者的電腦和手機(jī)虑瀑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)湿滓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人舌狗,你說(shuō)我怎么就攤上這事叽奥。” “怎么了痛侍?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵朝氓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我主届,道長(zhǎng)赵哲,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任君丁,我火速辦了婚禮枫夺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绘闷。我一直安慰自己橡庞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布印蔗。 她就那樣靜靜地躺著扒最,像睡著了一般。 火紅的嫁衣襯著肌膚如雪喻鳄。 梳的紋絲不亂的頭發(fā)上扼倘,一...
    開(kāi)封第一講書(shū)人閱讀 51,775評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音除呵,去河邊找鬼再菊。 笑死,一個(gè)胖子當(dāng)著我的面吹牛颜曾,可吹牛的內(nèi)容都是我干的纠拔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼泛豪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼稠诲!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起诡曙,我...
    開(kāi)封第一講書(shū)人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤臀叙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后价卤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體劝萤,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年慎璧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了床嫌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跨释。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖厌处,靈堂內(nèi)的尸體忽然破棺而出鳖谈,到底是詐尸還是另有隱情,我是刑警寧澤阔涉,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布缆娃,位于F島的核電站,受9級(jí)特大地震影響洒敏,放射性物質(zhì)發(fā)生泄漏龄恋。R本人自食惡果不足惜疙驾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一凶伙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧它碎,春花似錦函荣、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至挖息,卻和暖如春金拒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背套腹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工绪抛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人电禀。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓幢码,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親尖飞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子症副,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容