如何检查数据是否已插入Room数据库

21

我在项目中使用了新的架构组件中的Room数据库。我通过dao添加了一些数据,但是当尝试检索它时却没有得到结果。您能否建议我如何检查插入是否成功?以下是代码以帮助您理解问题。

向数据库添加数据后,我使用调试器进行了检查,该语句已经成功执行。

appContext.db.rallyDAO().addVehicleListItem(vehicle)

在插入操作后,从数据库获得此语句的空值。

val v = appContext.db.rallyDAO().getVehicleListItem(it.vehicleID)

RoomDatabase

的中文是

房间数据库

@Database(entities = arrayOf(Rally::class, Route::class, CheckPoints::class, Vehicles::class, VehicleListItem::class), version = 1)
abstract class TSDRoom: RoomDatabase() {
    public abstract fun rallyDAO():RallyDAO
}

DAO 内部

@Insert(onConflict = OnConflictStrategy.REPLACE)
    fun addVehicleListItem(vehicleListItem:VehicleListItem)

    @Query("select * from vehicles_submitted where vehicle_id LIKE :vehicleID")
    fun getVehicleListItem(vehicleID:String):VehicleListItem

车辆列表项实体

@Entity(tableName = "vehicles_submitted",
        foreignKeys = arrayOf(ForeignKey(entity = Rally::class,
                parentColumns = arrayOf("rally_id"),
                childColumns = arrayOf("rally_id"))))
class VehicleListItem {
    @PrimaryKey
    @ColumnInfo(name = "vehicle_id")
    @SerializedName("vehicle_id")
    var vehicleID : String = ""
    @ColumnInfo(name = "driver_id")
    @SerializedName("driver_id")
    var driverID : String = ""
    @ColumnInfo(name = "vehicle_name")
    @SerializedName("vehicle_name")
    var vehicleName : String = ""
    @ColumnInfo(name = "driver_name")
    @SerializedName("driver_name")
    var driverName : String = ""
    @ColumnInfo(name = "driver_email")
    @SerializedName("driver_email")
    var driverEmail : String = ""

    @ColumnInfo(name = "rally_id")
    @SerializedName("rally_id")
    var rallyID: String = ""

    @ColumnInfo(name = "is_passed")
    @SerializedName("is_passed")
    var isPassed = false

    @ColumnInfo(name = "passing_time")
    @SerializedName("passing_time")
    var passingTime:String=""
}
8个回答

18

问题出在线程中。 Room不允许您在主线程中运行数据库查询。insert方法的调用位于try-catch块内,我忽略了异常。 我已经修复了它,现在它的读取方式如下所示。

doAsync {
                        val addedID = appContext.db.rallyDAO().addVehicleListItem(vehicle)
                        Logger.d("vehicle_lsit_item","Inserted ID $addedID")
        }

我还查阅了文档,发现insert方法会返回Long(如果传入的是List,则返回Long列表)。我还更改了insert的签名,以下是修改后的代码:

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun addVehicleListItem(vehicleListItem:VehicleListItem):Long

P.S. 我正在使用anko来执行doAsync


7
你可以使用 Stetho 工具,在 Chrome 开发工具中查看你的数据库和共享偏好文件。
http://facebook.github.io/stetho/
编辑:AS 现在已经内置了数据库工具。

5

关于插入,有两种情况。

使用@Insert注解的Dao方法返回:

  1. In case the input is only one number it returns a Long, check whether this Long equals One, if true then the Item was added successfully.

     @Insert
     suspend fun insert( student: Student): Long
    
  2. In case the input is varargs it returns a LongArray, check whether the size of varargs equals the LongArray size, if true then items were added successfully

     @Insert
     suspend fun insert(vararg students: Student): LongArray
    

insertAll怎么样? - Jaimin Modi
1
第二个代码块插入多个项,它接受一个可变参数。 - هيثم
请注意,对于情况1,返回值并不总是One,而是插入项的新行ID。 - CodePlay

5

如果您没有访问权限问题,可以考虑一种选项,即直接导航到设备的sqlite实例并在那里直接查询表。

如果您使用Android Studio集成的模拟器或已经root的手机,可以执行以下操作:

adb root
adb remount
cd data/data/path/of/your/application/database
sqlite3 mydb.db

然后您可以查询您的数据表。

我在 remount 上遇到了很多错误,这些错误可以总结为 ERROR: *只读文件系统 - Mario Codes

3

你可以通过多种方式进行测试。

  1. 正如@Ege Kuzubasioglu所提到的,您可以使用stetho手动检查(需要对代码进行轻微更改)。
  2. 将数据库文件从"data/data/yourpackage/databases/yourdatabase.db" 拉取到本地计算机,并使用任何应用程序读取数据库中的内容。我个人使用https://sqlitebrowser.org/。 可以使用shell命令或使用android studio中的"设备文件浏览器"来拉取数据库文件。

  3. 编写TestCase以查看它是否工作。以下是我的一个项目中的测试用例示例。

    //来自我的DAO类的代码

    @Insert(onConflict = OnConflictStrategy.REPLACE) public abstract Long[] insertPurchaseHistory(List MusicOrders);

//我的测试用例 @Test public void insertPurchaseHistoryTest() {

    // Read test data from "api-responses/music-purchase-history-response.json"
    InputStream inputStream = getClass().getClassLoader()
            .getResourceAsStream("api-responses/music-purchase-history-response.json");
    // Write utility method to convert your stream to a string.
    String testData = FileManager.readFileFromStream(inputStream);

    // Convert test data to "musicOrdersResponse"
    MusicOrdersResponse musicOrdersResponse = new Gson().fromJson(testData,MusicOrdersResponse.class);

    // Insert inmateMusicOrders and get the list of
    Long[] rowsInserted = tracksDao.insertPurchaseHistory(musicOrdersResponse.getmusicOrders());
    assertThat(rowsInserted.length,Matchers.greaterThan(0));
}

Room 数据库操作难道没有回调函数吗? - zulkarnain shah
#2 对我不起作用,尽管我可以通过数据库查询并清楚地看到有数据返回。 SQLiteBrowser 显示下载的数据库为空。 - AdamHurwitz

2
您可以使用 Android Debug Database 通过 Web 浏览器访问应用程序的数据库。Android Debug Database 通过嵌入式 Web 服务器公开了这些数据库。
使用方法如下:
  1. Include it as debugImplementation dependency in your app's build.gradle so that it will only be included in debug build and not in release build:

    debugImplementation 'com.amitshekhar.android:debug-db:1.0.3'
    
  2. Start the debug build of your app

  3. The embedded web server launches automatically and announces its address and port in the logs:

    D/DebugDB: Open http://XXX.XXX.X.XXX:8080 in your browser
    
  4. If you are running the app over USB, setup portforwarding:

    adb forward tcp:8080 tcp:8080
    

    If you are not running the app over USB, your Android phone and workstation need to be in the same network and your workstation should be able to ping the Android phone.

  5. Finally, open the link from the logs in the browser.

请注意,它在不对设备进行root的情况下也可以正常工作,因为Web服务器在您的应用程序上下文中运行。

许多人点赞,也有许多人点踩,所以似乎对一些人有效,而对另一些人无效。向那些点踩的人请求帮助 - 你能解释一下你看到了什么错误或者为什么不喜欢这种方法吗? - mrts

1

最简单的方法之一是:

  1. 首先在Android Studio中下载DB Navigator插件(更多信息请访问:https://plugins.jetbrains.com/plugin/1800-database-navigator)。

  2. 转到视图> 工具窗口> 设备文件浏览器并下载您的DB实例。

  3. 打开DB Browser(从左侧窗格)并浏览您已下载的DB实例。设置连接,您就可以浏览数据库了。

  4. 有关更多信息,请参阅上面提供的链接。


0
我是这样做的(我使用协程 suspend):
class SaveVehicle(val repository: RepositoryInterface) {
    suspend fun invoke(vehicleListItem: VehicleListItem): VehicleListItem = 
        with(vehicleListItem) {
           also {
                 repository.saveVehicle(vehicleListItem)
           }
        }
}

Kotlin文档

inline fun <T> T.also(block: (T) -> Unit): T

调用指定的函数块并将此值作为其参数,并返回此值。 also 适用于执行需要上下文对象作为参数的某些操作。对于需要引用而不是对象的属性和函数的操作,请使用 also,或者当您不想从外部范围遮蔽此引用时使用。
您可以查看 我在GitHub上的示例

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接