首页 > 解决方案 > 无法阻止 Android 房间数据库中的触发器递归

问题描述

我无法阻止房间数据库中的递归触发器。每当 RecipeEntity 通过更新触发器发生值更改时,我都会尝试将我的 RecipeEntity 表中的 is_updated 列更新为 false。

                // prevent recursion
                db.execSQL("PRAGMA recursive_triggers = OFF;");

                // create recipe trigger to update is_updated to false every time recipe is updated
                db.execSQL("CREATE TRIGGER is_updated_trigger BEFORE UPDATE" +
                        "       ON RecipeEntity" +
                        "       BEGIN" +
                        "           UPDATE RecipeEntity SET is_updated=false" +
                        "           WHERE recipeId = NEW.recipeId; " +
                        "       END; "); 

这在使用 RoomDatabase.Callback() 通过 onCreate 创建数据库时调用;

更新 RecipeEntity 的查询只是一个普通的 Room @Update 方法。

错误信息:

2021-05-25 15:03:07.422 4668-4821/com.habbybolan.groceryplanner E/SQLiteLog: (1) statement aborts at 64: [UPDATE OR ABORT `RecipeEntity` SET `recipeId` = ?,`onlineRecipeId` = ?,`name` = ?,`is_favorite` = ?,`description` = ?,`prep_time` = ?,`cook_time` = ?,`serving_size` = ?,`calories` = ?,
    
    
    --------- beginning of crash
2021-05-25 15:03:07.429 4668-4821/com.habbybolan.groceryplanner E/AndroidRuntime: FATAL EXCEPTION: Thread-3
    Process: com.habbybolan.groceryplanner, PID: 4668
    android.database.sqlite.SQLiteException: too many levels of trigger recursion (code 1 SQLITE_ERROR)
        at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:890)
        at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:756)
        at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:66)
        at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeUpdateDelete(FrameworkSQLiteStatement.java:46)
        at androidx.room.EntityDeletionOrUpdateAdapter.handle(EntityDeletionOrUpdateAdapter.java:70)
        at com.habbybolan.groceryplanner.database.dao.RecipeDao_Impl.updateRecipes(RecipeDao_Impl.java:531)
        at com.habbybolan.groceryplanner.database.DatabaseAccessImpl.lambda$updateRecipe$14$DatabaseAccessImpl(DatabaseAccessImpl.java:427)
        at com.habbybolan.groceryplanner.database.-$$Lambda$DatabaseAccessImpl$3OxencYWN3idP4iK5ncgMxJDuQc.run(Unknown Source:4)
        at java.lang.Thread.run(Thread.java:923)
2021-05-25 15:03:07.453 1017-1023/? E/statsd: Predicate 5980654721335871649 dropping data for dimension key (10)0x2010101->10361[I] (10)0x30000->*launch*[S] 
2021-05-25 15:03:07.488 1620-2075/? E/InputDispatcher: channel '99b1b43 Toast (server)' ~ Channel is unrecoverably broken and will be disposed!

出于某种原因,当我从设备下载数据库并在 DB Browser 软件中运行它时,它可以正常工作而不会导致任何触发递归。这似乎是特定于 Room 的东西?

任何见解将不胜感激。谢谢你的帮助。

标签: androidandroid-room

解决方案


我相信你的问题是你似乎只在onCreate回调中发出 PRAGMA 。

这个回调只会被调用一次,我不相信状态会持续存在。因此,RECURSIVE_TRIGGERS 为 ON(左为 ON)。

我建议添加一个onOpen回调来执行 PRAGMA。


推荐阅读