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ù)干貨惜纸。