我正在開發一個基于 Java 的 Android 應用程式,我正在使用 Room。應用程式連接到服務器,從中下載專案特定的配置。這些配置之一是設定表。我有一個表格,其中每個專案的列數和型別都不同。我需要在手機上有這個表的本地副本來存盤資料,以防沒有互聯網連接可用。表的配置包含表名和列組成,如
[{
"name":"column1",
"datatype":"VARCHAR(20)"
},
{
"name":"column2",
"datatype":"INT(5)"
},
{
"name":"column3",
"datatype":"DOUBLE"
}]
如何使用 Room 生成這樣的表?生成創建查詢不是問題,但我應該在哪里執行它。另外,如何插入、更新和查詢表中的資料?是否可以生成這樣的 SQL 查詢并執行它們?有沒有類似行映射器的東西可以用來從表中讀取查詢的資料?如果這是不可能的,那么我知道如何解決它嗎?謝謝您的支持。
uj5u.com熱心網友回復:
您將無法使用 Room 并使用 Room 的物件映射來執行此操作,因為 Room 根據物件的映射構建表。
- 那就是一個表是根據一個用@Entity 注釋的類定義的,并定義為資料庫的物體。
它在編譯時承擔了很多作業,例如驗證構建它的組件創建 SQL 的查詢。在運行時,作為打開資料庫的一部分,它會檢查預期的組件,如果發現差異,則會失敗/崩潰。
我曾經有一個專案正在進行中,該專案基于可以復制到專案中的資料庫構建物體/類,但房間更改和引入功能(例如,默認約束被忽略但隨后引入)。
您可以擁有不受 Room 控制/已知的組件(包括表),這不會違反運行時模式檢查,但是您必須使用 SupportSQLiteDatabase,因此您不妨使用本機 SQLite。
如何使用 Room 生成這樣的表?
在示例的情況下,您將需要一個用@Entity 注釋的類。然而,Room 強加的一個規則是必須有一個 PRIMARY KEY。因此,一種選擇可能是引入一個。讓我們說一個名為id的列
Room 強制執行的另一個規則是列型別只能是 INTEGER、TEXT、REAL 或 BLOB。然而,這是由變數型別決定的。
- 所以 VARCHAR(50) 將用于字串,
- INT(5) 可能會存盤 long 或 int long 將涵蓋所有內容。
- DOUBLE 可能會將 DOUBLE (REAL) 存盤為兩倍。
所以類(物體)可能是:-
@Entity
class TableX {
@PrimaryKey
Long id = null;
String column1;
long column2;
double column3;
}
- 表名將是 TableX
如何插入、更新和查詢表中的資料?
您使用帶有@Dao 注釋的介面或抽象類,因此對于上述內容,例如,您可以具有:-
@Dao
abstract class TableXDao {
@Insert
abstract long insert(TableX tableX);
@Insert
abstract long[] insert(TableX...tableX);
@Query("INSERT INTO TableX (column1,column2,column3) VALUES(:column1,:column2,:column3)")
abstract long insert(String column1,long column2, double column3);
@Update
abstract int update(TableX tableX);
@Update
abstract int update(TableX...tableX);
@Query("UPDATE tablex set column1=:newColumn1, column2=:newColumn2,column3=:newColumn3 WHERE id=:id")
abstract int update(long id, String newColumn1, long newColumn2, double newColumn3);
@Query("SELECT * FROM tablex")
abstract List<TableX> getAllTableXRows();
}
- 注意插入/更新的 3 種形式 @Insert/@Update 使用方便的方法(基于傳遞一個或多個物件)@Query 使用更自由格式/適應性的方法。
盡管沒有要求 Room 需要了解資料庫本身,因此需要使用@Database 注釋的另一個類,該注釋定義了構成資料庫的物體、版本號(和其他選項)。該類應該擴展 RoomDatabase 類,它必須是一個抽象類或實作抽象方法createOpenHelper(通常是前者)。所以 :-
@Database(entities = {TableX.class},version = 1)
abstract class TheDatabase extends RoomDatabase {
abstract TableXDao getTableXDao();
/* Often :- */
private static volatile TheDatabase instance = null;
public TheDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(
context,TheDatabase.class,"thedatabase.db"
)
.build();
}
return instance;
}
}
當以上編譯完成時,構建將包括一個警告:-
E:\AndroidStudioApps\SO70351715JavaSQLite\app\src\main\java\a\a\so70351715javasqlite\TheDatabase.java:10: warning: Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide `room.schemaLocation` annotation processor argument OR set exportSchema to false.
abstract class TheDatabase extends RoomDatabase {
^
1 warning
- 故意允許發生以展示廣泛的編譯時間檢查
此外,它會生成相當多的 Java 代碼:-

所述TableXDao_Impl類為代碼時道的使用的被呼叫TheDatabase_Impl類是用于訪問資料庫,包括創建在createAllTables方法的表的代碼: -
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `TableX` (`id` INTEGER, `column1` TEXT, `column2` INTEGER NOT NULL, `column3` REAL NOT NULL, PRIMARY KEY(`id`))");
_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, '5f1c580621c8b86aef3b3cccc44d8d76')");
}
正如您所看到的,room_master_table 被創建并填充了一行存盤哈希值,這是驗證的一部分,如果哈希值發生更改,則房間將知道架構已更改(源代碼已更改)。
有沒有類似行映射器的東西可以用來從表中讀取查詢的資料?
可以看出,所有這些都是通過注釋使用編譯后的代碼完成的,因此沒有映射,而是期望在編譯時知道/定義所有內容。
如果這是不可能的,那么我知道如何解決它嗎?使用 Native SQLite 或統一管理服務器資料庫和房間資料庫。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/382479.html
標籤:爪哇 安卓 sqlite android-room
上一篇:SQLAlchemy:AttributeError:無法在“_sa_instance_state”列的行中找到列
