Android Room数据库DAO调试日志

IHe*_*oid 28 logging android android-room

给出像这样的房间数据库DAO:

import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Query;

import java.util.Date;
import java.util.List;

@Dao
public interface MyDao {

    @Query("SELECT * FROM MyTable")
    List<MyItem> all();

    @Query("SELECT * FROM MyTable WHERE date = :date AND language = :language")
    MyItem byDate(Date date, String language);


}
Run Code Online (Sandbox Code Playgroud)

有没有办法添加一个Logger或类似的东西,MyDao以便我可以看到正在执行哪些语句.这在开发过程中非常有用,因为我可以立即检查函数是否正确转换为预期的SQL语句.

Com*_*are 16

在DAO级别似乎没有任何钩子.有与数据库打开和升级相关的回调,但不是任意的东西.

但是,您可以提交功能请求.我同意它可能有用.更好的是OkHttp风格的通用拦截器框架.


Pin*_*kin 14

根据Room的文档,它执行编译时间检查,因此如果您的SQL语句无效,编译本身就会失败并且日志中会显示正确的错误消息.

默认情况下,生成的代码也是可调试的,可以在下面提到的路径下找到.

build> generated> source> apt> your Package> yourDao_Impl.java

此类包含DAO的实现,您可以在调试项目中的其他类时调试此类.:-)

示例:

在此输入图像描述

  • 谢谢你的回复.我在调试时看到了`_Impl`,但我找不到一个完整的字符串,其中所有占位符都已填充参数.也许我错过了? (3认同)

Ale*_*pov 13

假设Room使用框架的Sqlite作为基础数据库,则可以很简单地记录这些语句。唯一的限制:这只能在模拟器上完成。

SQLiteDebug.java中

/**
 * Controls the printing of SQL statements as they are executed.
 *
 * Enable using "adb shell setprop log.tag.SQLiteStatements VERBOSE".
 */
public static final boolean DEBUG_SQL_STATEMENTS =
        Log.isLoggable("SQLiteStatements", Log.VERBOSE);  
Run Code Online (Sandbox Code Playgroud)

默认情况下,log.tag.SQLiteStatements未设置的值:

alex @ mbpro:〜$ adb shell getprop log.tag.SQLiteStatements
<-空白行->

根据上述文档,要设置属性,我们必须使用:

亚历克斯@ mbpro:〜$ ADB壳setprop log.tag.SQLiteStatements VERBOSE
亚历克斯@ mbpro:〜$ ADB壳getprop log.tag.SQLiteStatements
VERBOSE

如我们所见,该VERBOSE值已成功设置。但是,如果我们重新运行我们的应用程序-我们将看不到这些语句。为了使其正常工作,我们必须使用然后重新启动所有服务。 如果您尝试使用常规设备执行此操作,则会收到以下错误(已在Pixel XL / Android 9上尝试过): adb shell stopadb shell start

alex @ mbpro:〜$ adb shell start
开始:必须是root
alex @ mbpro:〜$ adb root
adbd无法在生产版本中作为root运行

这就是为什么我们必须使用仿真器的原因:

alex @ mbpro:〜$ adb root
以root身份重新启动adbd
alex @ mbpro:〜$ adb shell stop
alex @ mbpro:〜$ adb shell start

仿真器将重新启动。
运行您的应用程序,您将在logcat中看到类似的Sqlite语句:

<redacted..>
V/SQLiteStatements: <redacted>/my_db: "BEGIN EXCLUSIVE;"
V/SQLiteStatements: <redacted>/my_db: "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)"
V/SQLiteStatements: <redacted>/my_db: "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, "3cb5664b6da264c13388292d98141843")"
V/SQLiteStatements: <redacted>/my_db: "CREATE TABLE IF NOT EXISTS `MyTable` (`id` TEXT NOT NULL, `date` INTEGER, `language` TEXT, PRIMARY KEY(`id`))"
<redacted..>
V/SQLiteStatements: <redacted>/my_db: "BEGIN EXCLUSIVE;"
V/SQLiteStatements: <redacted>/my_db: "PRAGMA temp_store = MEMORY;"
V/SQLiteStatements: <redacted>/my_db: "PRAGMA recursive_triggers='ON';"
V/SQLiteStatements: <redacted>/my_db: "CREATE TEMP TABLE room_table_modification_log(version INTEGER PRIMARY KEY AUTOINCREMENT, table_id INTEGER)"
V/SQLiteStatements: <redacted>/my_db: "COMMIT;"
<redacted..>
V/SQLiteStatements: <redacted>/my_db: "SELECT * FROM MyTable"
V/SQLiteStatements: <redacted>/my_db: "SELECT * FROM MyTable WHERE date = 1551562171387 AND language = 'en'"  
Run Code Online (Sandbox Code Playgroud)

要撤消更改,请使用以下命令:

alex @ mbpro:〜$ adb shell setprop log.tag.SQLiteStatements \“ \”
alex @ mbpro:〜$ adb shell getprop log.tag.SQLiteStatements
<-空白->
alex @ mbpro:〜$ adb shell stop
alex @mbpro:〜$ adb shell启动
alex @ mbpro:〜$ adb
unroot以非root 身份重新启动adbd

  • 这对我来说非常有帮助。谢谢。 (5认同)
  • @AndroidDev123您应该使用允许提升权限的AOSP系统映像,根据[此描述](https://developer.android.com/studio/run/managing-avds#system-image)。 (2认同)

geo*_*sey 10

Room 2.3.0-alpha04(于 2020 年 12 月 16 日发布,在您阅读本文时可能稳定)开始,Room 直接支持使用新版本记录 SQL 查询RoomDatabase.QueryCallback

你在 RoomDatabase.Builder

    fun getDatabase(context: Context): MyDatabase {
        val dbBuilder = Room.databaseBuilder(
            context.applicationContext,
            MyDatabase::class.java, "mydatabase.db"
        )
        dbBuilder.setQueryCallback(RoomDatabase.QueryCallback { sqlQuery, bindArgs ->
            println("SQL Query: $sqlQuery SQL Args: $bindArgs")
        }, Executors.newSingleThreadExecutor())
        return dbBuilder.build()
    }
Run Code Online (Sandbox Code Playgroud)

请注意,这只是示例代码,您可能应该确保MyDatabase在您的应用程序中是单例。另一个提示是仅在应用程序处于调试状态时记录查询: if (BuildConfig.DEBUG) dbBuilder.setQueryCallback(...以及上面的其余代码。

评论是否有人想要 Java 中的示例代码


bit*_*ale 6

当我在Room db中插入或更新行时遇到一些未知错误时,Android在调试控制台中未显示任何错误。我发现如何检查调试时发生的事情是:

try { someSource.update(someRow) } catch (e: Throwable) { println(e.message) }
Run Code Online (Sandbox Code Playgroud)

输出为:

唯一约束失败:quiz.theme(代码2067)