如何从 Room 数据库中的列表中删除特定项

huangapple go评论73阅读模式
英文:

How to delete a specific item from a list in room db

问题

我想从Room数据库中的列表中删除单个项目,我已经查看了一些文档,其中在@Query中的SQL查询中使用了 json_remove() 函数,但它不起作用并且抛出错误。

这是我的DAO看起来像这样:

@Entity(tableName = "data_table")
@Serializable
data class DataTable(
    val name: String,
    @PrimaryKey
    val url: String,
    val addon: String
)

@Entity(tableName = "entries_table")
@Serializable
@TypeConverters(EntriesTypeConverter::class)
data class EntriesTable(
    @PrimaryKey
    val name: String,
    @TypeConverters(EntriesTypeConverter::class)
    val data: List<DataTable>,
)

现在我的问题是,我如何根据DataTable中的urlEntriesTable中的data中删除特定项目?

我曾使用以下查询语句,我对SQL不熟悉,我查看了来自 sqlite.org 和ChatGPT的示例,但我提取的只是以下查询,它不起作用:

@Query("UPDATE entries_table SET links = json_remove(data, (SELECT json_extract(data, '$[webURL = :url]') FROM entries_table WHERE name = :name)) WHERE name = :name")

我该如何解决这个问题,谢谢:)

英文:

i want to delete a single item from a list in room db, i've gone through few docs where it used json_remove() function within the SQL query in the @Query but it doesn't work and throws error;

this is how dao looks:

@Entity(tableName = &quot;data_table&quot;)
@Serializable
data class DataTable(
    val name: String,
    @PrimaryKey
    val url: String,
    val addon: String
)


@Entity(tableName = &quot;entries_table&quot;)
@Serializable
@TypeConverters(EntriesTypeConverter::class)
data class EntriesTable(
    @PrimaryKey
    val name: String,
    @TypeConverters(EntriesTypeConverter::class)
    val data: List&lt;DataTable&gt;,
)

now my question is that how can i remove a specific item from the data in EntriesTable based on url which is in theDataTable

i was using this query statement, i'm new to sql things, i've gone thorough example from sqlite.org and from chatgpt, all i pulled was the following query, which doesnt work:

@Query(&quot;UPDATE entries_table SET links = json_remove(data, (SELECT json_extract(data, &#39;$[webURL = :url]&#39;) FROM entries_table WHERE name = :name)) WHERE name = :name&quot;)

how can i solve this, thankyou:)

答案1

得分: 0

以下是您提供的文本的中文翻译:

如果您使用类型转换器来存储一个列表,实际存储的数据是列表的表示形式作为单个值。SQLite(因此也是Room)不知道个别列表项,而是存储数据的列只是一个单一的包罗万象的值。

通常这样的类型转换器将是数据的JSON字符串表示,其中包含分隔符和名称,允许重建列表对象。

数据表的名称永远不会等于列,而只会成为列的一部分,所以您必须使用SQLite的instrLIKE与掩码来定位SQL的WHERE子句中的行或行。

  • 例如 UPDATE .... WHERE instr(data,:name)UPDATE .... WHERE data LIKE('&amp;#39;*&amp;#39;||:name||'&amp;#39;*)
  • .... SET links 会有问题,因为根据您的EntriesTable类,没有名为links的字段,因此也没有名为links的列。
  • 无论是instr还是LIKE与掩码都将非常消耗资源,列表越长,消耗的资源就越多。

备选方法

我建议,考虑到您有两个表(即两个带有@Entity注释的类),您可以利用数据库的关系特性,这将更容易地实现对EntriesTable的DataTables的操作,即数据字段/列。

通过这种方法,与其在两个表中存储相同的数据(如果DataTables实际上是一个表的话),您可以有一个用于条目的表和一个用于数据的表,后者包括从data_table行到其父entries_table行的链接(引用/映射)。

在最简单的形式中,entries_table可以是:-

@Entity(tableName = &quot;entries_table&quot;)
data class EntriesTable(
    @PrimaryKey
    val name: String
)
  • 即列表将是相关的data_table行

在最简单的形式中,data_table可以是:-

@Entity
data class DataTable(
    val name: String,
    @PrimaryKey
    val url: String,
    val addon: String,
    @ColumnInfo(index = true)
    val entries_reference: String
)
  • 注意添加的字段entries_reference,为了访问效率而进行索引

然而,由于在data_table中没有引用/链接到父级的data_table行可能会浪费,所以您可能希望包括有效链接(通常称为引用完整性)的强制执行。因此,您可能希望包括外键约束,基本上表示data_table中的行必须具有父行。因此,DataTable类可以是:-

@Entity(
    tableName = &quot;data_table&quot;,
    foreignKeys = [
        ForeignKey(
            entity = EntriesTable::class,
            parentColumns = [&quot;name&quot;],
            childColumns = [&quot;entries_reference&quot;],
            onDelete = ForeignKey.CASCADE,
            onUpdate = ForeignKey.CASCADE
        )
    ]
)
data class DataTable(
    val name: String,
    @PrimaryKey
    val url: String,
    val addon: String,
    @ColumnInfo(index = true)
    val entries_reference: String
)
  • onDelete将在删除父级时自动删除子级。
  • onUpdate将在更改父级的name时自动更新entries_reference的值。
  • 这两个选项可能是可用ON ACTION选项中最有用的两个。

使用这种结构,删除data_table行实际上会更新列表(稍后将进行演示)。这是您希望根据您的问题执行的任务。

您很可能希望检索带有相关data_tables列表的entries_table行,为此您可以使用如下的POJO:-

/* 用于获取带有相关子级(data_table行)的条目的POJO */
data class EntryWithData(
    @Embedded
    val entriesTable: EntriesTable,
    @Relation(
        entity = DataTable::class,
        parentColumn = &quot;name&quot;,
        entityColumn = &quot;entries_reference&quot;
    )
    val dataTableList: List&lt;DataTable&gt;
)

以下是包括2个可用于完成问题任务(即从data_tables列表中删除data_table)的DAO函数:-

@Dao
interface AllDAOs {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insert(dataTable: DataTable): Long
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insert(entriesTable: EntriesTable): Long
    /* 便利删除注意,room使用主键值(url)来确定要删除的内容(请参见工作演示) */
    @Delete
    fun delete(entriesTable: EntriesTable): Int
    /* 根据提供的url删除 注意,删除条目是不相关的,因为EntriesTable将具有0个或更多个DataTable行的列表 */
    @Delete
    fun delete(dataTable: DataTable): Int
    @Query(&quot;DELETE FROM data_table WHERE url=:url&quot;)
    fun deleteByUrl(url: String)
    /* 获取所有数据表的查询 */
    @Query(&quot;SELECT * FROM data_table&quot;)
    fun getAllDataTables(): List&lt;DataTable&gt;
    /* 获取所有具有相关DataTable列表(每个EntriesTable对象及其DataTable列表)的EntriesWithData对象的查询 */
    @Transaction
    @Query(&quot;SELECT * FROM entries_table&quot;)
    fun getAllEntriesWithRelatedDataTableList(): List&lt;EntryWithData&gt;
}

演示


为了演示建议的结构,这里有一个简单的@Database注释的类(请注意,为了简洁起见,将使用主线程):-

@Database(entities = [DataTable::class,EntriesTable::class], exportSchema = false, version = 1)
abstract class TheDatabase: RoomDatabase() {
    abstract fun getAllDAOs(): AllDAOs

    companion object {
        private var instance: TheDatabase?=null
        fun getInstance(context: Context): TheDatabase {
            if (instance==null) {
                instance=Room.databaseBuilder(context,TheDatabase::class.java,&quot;the_database.db&quot;)
                    .allowMainThreadQueries()
                    .build()
            }
            return instance as TheDatabase
        }
    }
英文:

If you use a Type Converter to store a list that actual data stored is a representation of the list as a single value. SQLite (and therefore Room) does not know about individual list items rather the column where the data is stored is just a single all encompassing value.

Typically such a Type Converter will be a JSON String representation of the data with separators and names allowing the list object to be reconstructed.

A DataTables name will never equate to a column, rather it would be part of a column so you would have to use either the SQLite instr or a LIKE with a mask to locate the row or rows for the WHERE clause of the SQL.

  • e.g. UPDATE .... WHERE instr(data,:name) or UPDATE .... WHERE data LIKE(&#39;*&#39;||:name||&#39;*&#39;).
  • .... SET links is going to be problematic as there is, according to your EntriesTable class, there is no field and thus column named links.
  • both instr and the LIKE with a mask will be quite resource expensive, and more so the longer the list.

Alternative Approach

I would suggest, seeing that you have two tables (i.e. two @Entity annotated classes) that you instead utilise the relational aspect of the database which would easily facilitate manipulation of DataTables per EntriesTable i.e. the data field/column.

With this approach instead of storing the same data in both tables (if DataTable is in fact a table) you have a table for the entries and a table for the datas, the latter including a link (reference/map) from a data_table row to it's parent entries_table row.

In the simplest form, the entries_table could be:-

@Entity(tableName = &quot;entries_table&quot;)
data class EntriesTable(
    @PrimaryKey
    val name: String
)
  • i.e. the list will be the related data_table rows

In the simplest form data_table could be:-

@Entity
data class DataTable(
    val name: String,
    @PrimaryKey
    val url: String,
    val addon: String,
    @ColumnInfo(index = true)
    val entries_reference: String
)
  • note the added field entries_reference, which for access efficiency is indexed

However, as a row in the data_table that does not have a reference/link to a parent would likely be a waste it might be an idea to include enforcement of valid links (what is often termed as referential integrity). Thus you may well wish to include Foreign Key constraints that basically say that a row in the data_table MUST have a parent. As such the DataTable class could be:-

@Entity(
    tableName = &quot;data_table&quot;,
    foreignKeys = [
        ForeignKey(
            entity = EntriesTable::class,
            parentColumns = [&quot;name&quot;],
            childColumns = [&quot;entries_reference&quot;],
            onDelete = ForeignKey.CASCADE,
            onUpdate = ForeignKey.CASCADE
        )
    ]
)
data class DataTable(
    val name: String,
    @PrimaryKey
    val url: String,
    val addon: String,
    @ColumnInfo(index = true)
    val entries_reference: String
)
  • The onDelete will delete the children of the parent automatically if the parent is deleted.
  • The onUpdate will automatically update the value of the entries_reference if the name of the parent is changed.
  • these two are perhaps the most useful of the available ON ACTION options.

With this structure the deletion of a data_table row effectively updates the list (as will be demonstrated later). This being the task that you wish to accomplish according to your question.

You would very likely want to retrieve entries_table rows along with the respective list of data_tables, for this you could have a POJO such as:-

/* POJO for getting Entries with the related children (data_table rows) */
data class EntryWithData(
    @Embedded
    val entriesTable: EntriesTable,
    @Relation(
        entity = DataTable::class,
        parentColumn = &quot;name&quot;,
        entityColumn = &quot;entries_reference&quot;
    )
    val dataTableList: List&lt;DataTable&gt;
)

The following are DAO functions, including 2 delete functions that could be used to accomplish what the task if the question (aka remove a data_table from a list of data_tables):-

@Dao
interface AllDAOs {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insert(dataTable: DataTable): Long
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun insert(entriesTable: EntriesTable): Long
    /* Convenience Deletes NOTE room uses the Primary Key value (url) to determine what to delete (see working demo) */
    @Delete
    fun delete(entriesTable: EntriesTable): Int
    /* Delete according to provided url */
    /* NOTE UPDATE to remove is irrelevant as an EntriesTable will have a List of 0 or more DataTable rows */
    @Delete
    fun delete(dataTable: DataTable): Int
    @Query(&quot;DELETE FROM data_table WHERE url=:url&quot;)
    fun deleteByUrl(url: String)
    /* Query to get all DataTables */
    @Query(&quot;SELECT * FROM data_table&quot;)
    fun getAllDataTables(): List&lt;DataTable&gt;
    /* Query to get all EntryWithData objects (Each EntriesTable Object with it&#39;s list of DataTables) */
    @Transaction
    @Query(&quot;SELECT * FROM entries_table&quot;)
    fun getAllEntriesWithRelatedDataTableList(): List&lt;EntryWithData&gt;
}

Demonstration


To facilitate demonstration of the suggested structure a simple @Database annotated class (noting that for brevity the main thread will be used):-

@Database(entities = [DataTable::class,EntriesTable::class], exportSchema = false, version = 1)
abstract class TheDatabase: RoomDatabase() {
    abstract fun getAllDAOs(): AllDAOs

    companion object {
        private var instance: TheDatabase?=null
        fun getInstance(context: Context): TheDatabase {
            if (instance==null) {
                instance=Room.databaseBuilder(context,TheDatabase::class.java,&quot;the_database.db&quot;)
                    .allowMainThreadQueries()
                    .build()
            }
            return instance as TheDatabase
        }
    }
}

To actually demonstrate then the following activity code:-

class MainActivity : AppCompatActivity() {

    lateinit var db: TheDatabase
    lateinit var dao: AllDAOs
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        db = TheDatabase.getInstance(this)
        dao = db.getAllDAOs()

        /* use the database to add some data, and then delete data, writing the contents of the tables at various stages */
        doSomeDbWork()
    }

    fun doSomeDbWork() {
        /* Add 4 EntriesTable rows */
        dao.insert(EntriesTable(&quot;Entry1&quot;))
        dao.insert(EntriesTable(&quot;Entry2&quot;))
        dao.insert(EntriesTable(&quot;Entry3&quot;))
        dao.insert(EntriesTable(&quot;Entry4&quot;))

        /* Add related DataTable rows, 3 related to Entry1, 3 related to Entry 2, 1 related to Entry3 and 1 related to Entry 4 */
        dao.insert(DataTable(&quot;DT01&quot;,&quot;dt01url&quot;,&quot;addonA&quot;,&quot;Entry1&quot;))
        dao.insert(DataTable(&quot;DT02&quot;,&quot;dt02url&quot;,&quot;addonB&quot;,&quot;Entry1&quot;))
        dao.insert(DataTable(&quot;DT03&quot;,&quot;dt03url&quot;,&quot;addonC&quot;,&quot;Entry1&quot;))
        dao.insert(DataTable(&quot;DT04&quot;,&quot;dt04url&quot;,&quot;addonA&quot;,&quot;Entry2&quot;))
        dao.insert(DataTable(&quot;DT05&quot;,&quot;dt05url&quot; ,&quot;addon1&quot;,&quot;Entry2&quot;))
        dao.insert(DataTable(&quot;DT06&quot;,&quot;dt06url&quot;,&quot;addonD&quot;,&quot;Entry2&quot;))
        dao.insert(DataTable(&quot;DT07&quot;,&quot;dt07url&quot;,&quot;addonE&quot;,&quot;Entry3&quot;))
        dao.insert(DataTable(&quot;DT08&quot;,&quot;dt08url&quot;,&quot;addonF&quot;,&quot;Entry4&quot;))

        /* Show the initial data */
        logEntriesWithDataTableLists(&quot;STAGE1&quot;)

        /* example of deleting non existent datatable */
        dao.delete(DataTable(&quot;does not matter&quot;,&quot;not a saved url&quot;,&quot;again does not matter&quot;,&quot;again does not matter&quot;))
        logEntriesWithDataTableLists(&quot;STAGE2&quot;)

        /* example of deleting existing datatable shows that all that matters is the Primary key value as that is what Room uses to ascertain what to delete */
        dao.delete(DataTable(&quot;does not matter&quot;,&quot;dt07url&quot;,&quot;again does not matter&quot;,&quot;again does not matter&quot;))
        logEntriesWithDataTableLists(&quot;STAGE3&quot;)
        /* example of alternative deleting by url */
        dao.deleteByUrl(&quot;dt01url&quot;)
        logEntriesWithDataTableLists(&quot;STAGE4&quot;)
        /* example of deleting an Entry and the deletion being cascaded to the children of the entry */
        dao.delete(EntriesTable(&quot;Entry3&quot;))
        logEntriesWithDataTableLists(&quot;STAGE5&quot;)
    }

    fun logEntriesWithDataTableLists(tagSuffix: String){
        for(ewd in dao.getAllEntriesWithRelatedDataTableList()) {
            val sb=StringBuilder()
            for (dt in ewd.dataTableList) {
                sb.append(&quot;\n\tDT name = ${dt.name} URL=${dt.url} ADDON=${dt.addon} REFERS TO PARENT ENTRY ${dt.entries_reference}&quot;)
            }
            Log.d(&quot;DBINFO_${tagSuffix}&quot;,&quot;Entry is ${ewd.entriesTable.name} it has ${ewd.dataTableList.size} related DT&#39;s. They are:-${sb}&quot;)
        }
        logAllDatatables(tagSuffix)
    }

    fun logAllDatatables(tagSuffix: String) {
        for (dt in dao.getAllDataTables()) {
            Log.d(&quot;DBINFO_DT_$tagSuffix&quot;,&quot;DT is ${dt.name} URL is ${dt.url} ADDON is ${dt.addon} REFERS TO PARENT ENTRY ${dt.entries_reference}&quot;)
        }
    }
}

Result

When run (for the first time) then the log includes:-

STAGE1

This is after the 4 rows have been added to the entries_table and the 8 rows have been added to the data_table table.

Of the 8 data_table rows 3 are related to Entry1, 2 are related to Entry2 and 1 each are related to Entry 3 and Entry 4.

2023-06-19 14:51:48.532 D/DBINFO_STAGE1: Entry is Entry1 it has 3 related DT&#39;s. They are:-
    	DT name = DT01 URL=dt01url ADDON=addonA REFERS TO PARENT ENTRY Entry1
    	DT name = DT02 URL=dt02url ADDON=addonB REFERS TO PARENT ENTRY Entry1
    	DT name = DT03 URL=dt03url ADDON=addonC REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.532 D/DBINFO_STAGE1: Entry is Entry2 it has 3 related DT&#39;s. They are:-
    	DT name = DT04 URL=dt04url ADDON=addonA REFERS TO PARENT ENTRY Entry2
    	DT name = DT05 URL=dt05url ADDON=addon1 REFERS TO PARENT ENTRY Entry2
    	DT name = DT06 URL=dt06url ADDON=addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.532 D/DBINFO_STAGE1: Entry is Entry3 it has 1 related DT&#39;s. They are:-
    	DT name = DT07 URL=dt07url ADDON=addonE REFERS TO PARENT ENTRY Entry3
2023-06-19 14:51:48.532 D/DBINFO_STAGE1: Entry is Entry4 it has 1 related DT&#39;s. They are:-
    	DT name = DT08 URL=dt08url ADDON=addonF REFERS TO PARENT ENTRY Entry4
2023-06-19 14:51:48.534 D/DBINFO_DT_STAGE1: DT is DT01 URL is dt01url ADDON is addonA REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.534 D/DBINFO_DT_STAGE1: DT is DT02 URL is dt02url ADDON is addonB REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.534 D/DBINFO_DT_STAGE1: DT is DT03 URL is dt03url ADDON is addonC REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.534 D/DBINFO_DT_STAGE1: DT is DT04 URL is dt04url ADDON is addonA REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.534 D/DBINFO_DT_STAGE1: DT is DT05 URL is dt05url ADDON is addon1 REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.534 D/DBINFO_DT_STAGE1: DT is DT06 URL is dt06url ADDON is addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.535 D/DBINFO_DT_STAGE1: DT is DT07 URL is dt07url ADDON is addonE REFERS TO PARENT ENTRY Entry3
2023-06-19 14:51:48.535 D/DBINFO_DT_STAGE1: DT is DT08 URL is dt08url ADDON is addonF REFERS TO PARENT ENTRY Entry4

STAGE2

This is after the attempt to delete row(s) that do not exist in the data_table i.e. the specified url is not a row.

  • note as will be shown later, the other values of the passed DataTable class are irrelevant.
    As such the resultant data is identical to STAGE1.

:-

2023-06-19 14:51:48.542 D/DBINFO_STAGE2: Entry is Entry1 it has 3 related DT&#39;s. They are:-
    	DT name = DT01 URL=dt01url ADDON=addonA REFERS TO PARENT ENTRY Entry1
    	DT name = DT02 URL=dt02url ADDON=addonB REFERS TO PARENT ENTRY Entry1
    	DT name = DT03 URL=dt03url ADDON=addonC REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.543 D/DBINFO_STAGE2: Entry is Entry2 it has 3 related DT&#39;s. They are:-
    	DT name = DT04 URL=dt04url ADDON=addonA REFERS TO PARENT ENTRY Entry2
    	DT name = DT05 URL=dt05url ADDON=addon1 REFERS TO PARENT ENTRY Entry2
    	DT name = DT06 URL=dt06url ADDON=addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.543 D/DBINFO_STAGE2: Entry is Entry3 it has 1 related DT&#39;s. They are:-
    	DT name = DT07 URL=dt07url ADDON=addonE REFERS TO PARENT ENTRY Entry3
2023-06-19 14:51:48.543 D/DBINFO_STAGE2: Entry is Entry4 it has 1 related DT&#39;s. They are:-
    	DT name = DT08 URL=dt08url ADDON=addonF REFERS TO PARENT ENTRY Entry4
2023-06-19 14:51:48.546 D/DBINFO_DT_STAGE2: DT is DT01 URL is dt01url ADDON is addonA REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.546 D/DBINFO_DT_STAGE2: DT is DT02 URL is dt02url ADDON is addonB REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.546 D/DBINFO_DT_STAGE2: DT is DT03 URL is dt03url ADDON is addonC REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.547 D/DBINFO_DT_STAGE2: DT is DT04 URL is dt04url ADDON is addonA REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.547 D/DBINFO_DT_STAGE2: DT is DT05 URL is dt05url ADDON is addon1 REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.547 D/DBINFO_DT_STAGE2: DT is DT06 URL is dt06url ADDON is addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.547 D/DBINFO_DT_STAGE2: DT is DT07 URL is dt07url ADDON is addonE REFERS TO PARENT ENTRY Entry3
2023-06-19 14:51:48.547 D/DBINFO_DT_STAGE2: DT is DT08 URL is dt08url ADDON is addonF REFERS TO PARENT ENTRY Entry4

STAGE3

Stage 3 is the deletion of a known/existing data_table row, i.e. the row that has the url value of dt07url (the 7th inserted data_table row which has Entry3 as it's parent).

  • Note how Entry3 now has 0 related data_tables in it's list as per D/DBINFO_STAGE3: Entry is Entry3 it has 0 related DT&#39;s. i.e. the list, which was just the 1 item, has been updated to be 0 items.

  • also note that even though the other fields of the passed DataTable are obviously incorrect, that the row is in fact deleted. i.e. confirming/demonstrating that it is just the PrimaryKey that is used to ascertain the row to be deleted.

:-

2023-06-19 14:51:48.554 D/DBINFO_STAGE3: Entry is Entry1 it has 3 related DT&#39;s. They are:-
    	DT name = DT01 URL=dt01url ADDON=addonA REFERS TO PARENT ENTRY Entry1
    	DT name = DT02 URL=dt02url ADDON=addonB REFERS TO PARENT ENTRY Entry1
    	DT name = DT03 URL=dt03url ADDON=addonC REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.555 D/DBINFO_STAGE3: Entry is Entry2 it has 3 related DT&#39;s. They are:-
    	DT name = DT04 URL=dt04url ADDON=addonA REFERS TO PARENT ENTRY Entry2
    	DT name = DT05 URL=dt05url ADDON=addon1 REFERS TO PARENT ENTRY Entry2
    	DT name = DT06 URL=dt06url ADDON=addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.555 D/DBINFO_STAGE3: Entry is Entry3 it has 0 related DT&#39;s. They are:-
2023-06-19 14:51:48.555 D/DBINFO_STAGE3: Entry is Entry4 it has 1 related DT&#39;s. They are:-
    	DT name = DT08 URL=dt08url ADDON=addonF REFERS TO PARENT ENTRY Entry4
2023-06-19 14:51:48.561 D/DBINFO_DT_STAGE3: DT is DT01 URL is dt01url ADDON is addonA REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.562 D/DBINFO_DT_STAGE3: DT is DT02 URL is dt02url ADDON is addonB REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.562 D/DBINFO_DT_STAGE3: DT is DT03 URL is dt03url ADDON is addonC REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.562 D/DBINFO_DT_STAGE3: DT is DT04 URL is dt04url ADDON is addonA REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.562 D/DBINFO_DT_STAGE3: DT is DT05 URL is dt05url ADDON is addon1 REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.562 D/DBINFO_DT_STAGE3: DT is DT06 URL is dt06url ADDON is addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.562 D/DBINFO_DT_STAGE3: DT is DT08 URL is dt08url ADDON is addonF REFERS TO PARENT ENTRY Entry4

STAGE4

Stage 4 deletes another row from the data_table, this time using the alternative delete function which is an @Query that takes just the url as it's parameter as opposed to the convenience @Delete which expects an object as it's parameter.

  • Note that the disadvantage with this approach is that the number of affected (deleted) rows is not returned.

:-

2023-06-19 14:51:48.567 D/DBINFO_STAGE4: Entry is Entry1 it has 2 related DT&#39;s. They are:-
    	DT name = DT02 URL=dt02url ADDON=addonB REFERS TO PARENT ENTRY Entry1
    	DT name = DT03 URL=dt03url ADDON=addonC REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.567 D/DBINFO_STAGE4: Entry is Entry2 it has 3 related DT&#39;s. They are:-
    	DT name = DT04 URL=dt04url ADDON=addonA REFERS TO PARENT ENTRY Entry2
    	DT name = DT05 URL=dt05url ADDON=addon1 REFERS TO PARENT ENTRY Entry2
    	DT name = DT06 URL=dt06url ADDON=addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.567 D/DBINFO_STAGE4: Entry is Entry3 it has 0 related DT&#39;s. They are:-
2023-06-19 14:51:48.567 D/DBINFO_STAGE4: Entry is Entry4 it has 1 related DT&#39;s. They are:-
    	DT name = DT08 URL=dt08url ADDON=addonF REFERS TO PARENT ENTRY Entry4
2023-06-19 14:51:48.570 D/DBINFO_DT_STAGE4: DT is DT02 URL is dt02url ADDON is addonB REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.570 D/DBINFO_DT_STAGE4: DT is DT03 URL is dt03url ADDON is addonC REFERS TO PARENT ENTRY Entry1
2023-06-19 14:51:48.570 D/DBINFO_DT_STAGE4: DT is DT04 URL is dt04url ADDON is addonA REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.570 D/DBINFO_DT_STAGE4: DT is DT05 URL is dt05url ADDON is addon1 REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.570 D/DBINFO_DT_STAGE4: DT is DT06 URL is dt06url ADDON is addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.570 D/DBINFO_DT_STAGE4: DT is DT08 URL is dt08url ADDON is addonF REFERS TO PARENT ENTRY Entry4

STAGE5

Stage 5 demonstrates the onDelete CASCADE option. The entries_table Entry1 row is deleted and as can be seen so are the 2 remain data_table rows.

2023-06-19 14:51:48.576 D/DBINFO_STAGE5: Entry is Entry2 it has 3 related DT&#39;s. They are:-
    	DT name = DT04 URL=dt04url ADDON=addonA REFERS TO PARENT ENTRY Entry2
    	DT name = DT05 URL=dt05url ADDON=addon1 REFERS TO PARENT ENTRY Entry2
    	DT name = DT06 URL=dt06url ADDON=addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.576 D/DBINFO_STAGE5: Entry is Entry3 it has 0 related DT&#39;s. They are:-
2023-06-19 14:51:48.576 D/DBINFO_STAGE5: Entry is Entry4 it has 1 related DT&#39;s. They are:-
    	DT name = DT08 URL=dt08url ADDON=addonF REFERS TO PARENT ENTRY Entry4
2023-06-19 14:51:48.580 D/DBINFO_DT_STAGE5: DT is DT04 URL is dt04url ADDON is addonA REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.580 D/DBINFO_DT_STAGE5: DT is DT05 URL is dt05url ADDON is addon1 REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.580 D/DBINFO_DT_STAGE5: DT is DT06 URL is dt06url ADDON is addonD REFERS TO PARENT ENTRY Entry2
2023-06-19 14:51:48.580 D/DBINFO_DT_STAGE5: DT is DT08 URL is dt08url ADDON is addonF REFERS TO PARENT ENTRY Entry4

答案2

得分: -1

查看DAO对象的定义 - https://developer.android.com/training/data-storage/room/accessing-data#anatomy

你可以在你的DAO中编写类似以下的代码:

@Dao
interface DataTableDao {
    ...
    @Delete
    fun delete(dataTable: DataTable)

    @Query("DELETE FROM datatable WHERE url = :urlInput")
    fun conditionalDelete(urlInput: String)
}

你可以使用 delete 函数(https://developer.android.com/training/data-storage/room/accessing-data#convenience-delete)来从DataTable中删除特定条目,或者你可以定义自己的查询(https://developer.android.com/training/data-storage/room/accessing-data#query)来执行更复杂的操作。

英文:

See the definition of DAO object - https://developer.android.com/training/data-storage/room/accessing-data#anatomy

You can write something like the following in your DAO:

@Dao
interface DataTableDao {
    ...
    @Delete
    fun delete(dataTable: DataTable)

    @Query(&quot;DELETE FROM datatable WHERE url = :urlInput&quot;)
    fun conditionalDelete(urlInput: String)
}

You can use the delete function (https://developer.android.com/training/data-storage/room/accessing-data#convenience-delete) to remove specific entry from DataTable, or you can define your own query (https://developer.android.com/training/data-storage/room/accessing-data#query) to do something more complex.

huangapple
  • 本文由 发表于 2023年6月18日 19:23:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76500285.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定