首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在android机房中插入、更新和删除多到多的关系?

如何在android机房中插入、更新和删除多到多的关系?
EN

Stack Overflow用户
提问于 2021-05-07 21:35:25
回答 1查看 1.2K关注 0票数 1

下面是Android文档中的多到多关系,请在这里找到:定义多到多的关系

我有以下实体

代码语言:javascript
运行
复制
@Entity
class Song(
    @PrimaryKey val songId: Long,
    @ColumnInfo val name: String,
    @ColumnInfo val path: Uri,
)
代码语言:javascript
运行
复制
@Entity
data class PlaylistInfo(
    @ColumnInfo var name: String,
    @PrimaryKey(autoGenerate = true) val playlistId: Long = 0,
)

然后,我有一个实体,是两者之间的交叉参照。

代码语言:javascript
运行
复制
@Entity(primaryKeys = ["playlistId", "songId"])
data class PlaylistSongCrossRef(
    val playlistId: Long,
    val songId: Long
)

最后,我有一个类,它使用PlaylistSongCrossRef作为连接将两者结合在一起。

代码语言:javascript
运行
复制
data class Playlist(
    @Embedded val info: PlaylistInfo,
    @Relation(
        parentColumn = "playlistId",
        entityColumn = "songId",
        associateBy = Junction(PlaylistSongCrossRef::class)
    )
    val songs: MutableList<Song>
)

然后,我在Dao中定义了读取查询。

这是文档的结尾。我现在正试图弄清楚如何插入、更新或删除一个Playlist

我尝试在Dao中定义函数,这些函数以Playlist作为参数,并使用@Insert@Update@Delete进行注释,但它们给出了以下错误:

错误:参数的类型必须是带有@Entity注释的类或其集合/数组。com.user.musicplayer.models.entities.Playlist播放列表

我不知道从这里往哪里走。如果有人能向我推荐一种资源,可以帮助我解决问题,或者给出一个可行的实现,那将是非常感谢的。

EN

回答 1

Stack Overflow用户

发布于 2021-05-08 15:22:42

我现在想弄清楚如何插入、更新或删除播放列表

播放列表是一个POJO,用于从数据库中提取数据,而不是修改数据库中的数据。也就是说,这是单向的。

但是,如果它不是一个数据类,而是一个类(我认为),那么您可以添加函数来执行这些操作。例如:

代码语言:javascript
运行
复制
class Playlist {

    @Embedded
    var playlistInfo: PlaylistInfo? = null
    @Relation(
        parentColumn = "playlistId",
        entityColumn = "songId",
        associateBy = Junction(PlaylistSongCrossRef::class)
    )
    var songs: MutableList<Song>? = null

    fun deletePlayList(dao: AllDao, playlist: Playlist, deleteOrphanedSongs: Boolean = false) {
        val currentPlaylistInfo: PlaylistInfo? = playlist.playlistInfo
        if (currentPlaylistInfo != null) {
            dao.deleteByPlayListId(currentPlaylistInfo.playlistId)
            dao.delete(currentPlaylistInfo)
            if (deleteOrphanedSongs) {
                dao.deleteManySongs(playlist.songs!!)
            }
        }
    }
}

你所能做的,用一个提取的播放列表是说删除播放列表和歌曲,如:-

代码语言:javascript
运行
复制
@Delete()
fun deletePlayListInfoAndSongs(playlistInfo: PlaylistInfo, songs: List<Song>): Int
  • 也就是说,使用提取的PlayList,您将有嵌入的PlaylistInfo和相关歌曲

但是,be 警告,上面的不会删除关联的PlaylistSongCrossRef行,因此最终会出现孤儿,这可能会有问题。

您可能希望考虑定义外键,并使用onDelete和/或onUpdate操作来级联删除。

Example/Demo

下面是一个基于实体的示例(为方便起见,歌曲路径改为字符串而不是URI )和上面的Playlist类。

刀供您考虑:-

代码语言:javascript
运行
复制
@Dao
interface AllDao {
    @Insert
    fun insert(playlistInfo: PlaylistInfo): Long
    @Insert
    fun insertManyPlaylistInfos(playlistInfoList: List<PlaylistInfo>): LongArray
    @Insert
    fun insert(song: Song): Long
    @Insert
    fun insertManySongs(songList: List<Song>): LongArray
    @Insert
    fun insert(playlistSongCrossRef: PlaylistSongCrossRef): Long
    @Insert
    fun insertManyPlaylistSongCrossrefs(playlistSongCrossRefList: List<PlaylistSongCrossRef>): LongArray

    @Query("SELECT * FROM song")
    fun getAllSongs(): List<Song>
    @Query("SELECT * FROM song WHERE song.name = :songname LIMIT 1")
    fun getFirstSongByName(songname: String): Song
    @Query("SELECT * FROM playlistInfo")
    fun getAllPlaylistInfos(): List<PlaylistInfo>
    @Query("SELECT * FROM playlistinfo WHERE playlistinfo.name = :playlistname LIMIT 1")
    fun getFirstPlaylistInfoByName(playlistname: String): PlaylistInfo
    @Query("SELECT * FROM playlistsongcrossref")
    fun getAllPlaylistSongCrossRefs(): List<PlaylistSongCrossRef>
    @Transaction
    @Query("SELECT * FROM playlistinfo")
    fun getAllPlaylists(): List<Playlist>

    @Query("SELECT count(*) FROM song")
    fun getNumberOfSongs(): Long
    @Query("SELECT count(*) FROM playlistinfo")
    fun getNumberOfPlaylistInfos(): Long
    @Query("SELECT count(*) FROM playlistsongcrossref")
    fun getNumberOfSongsInPlaylists(): Long
    @Update
    fun update(song: Song)
    @Update
    fun update(playlistInfo: PlaylistInfo)

    /* Suggested NEVER to use */
    @Update
    fun update(playlistSongCrossRef: PlaylistSongCrossRef)

    @Delete
    fun delete(playlistInfo: PlaylistInfo): Int
    @Delete()
    fun delete(song: Song): Int
    @Delete
    fun deleteManySongs(songs: List<Song>): Int
    @Delete
    fun delete(playlistSongCrossRef: PlaylistSongCrossRef): Int
    @Delete()
    fun deletePlayListInfoAndSongs(playlistInfo: PlaylistInfo, songs: List<Song>): Int
    //@Delete
    //fun deletePlayListInfoAndSongs(playlist: Playlist): Int
    @Query("DELETE FROM playlistsongcrossref WHERE playlistId = :playlistId")
    fun deleteByPlayListId(playlistId: Long): Int
    @Query("DELETE FROM playlistsongcrossref WHERE playlistId = :playlistId AND songId = :songId")
    fun deleteSongFromPlaylist(playlistId: Long, songId: Long)
}

在显示更新、删除和插入示例的活动中,可能需要考虑以下几点:

代码语言:javascript
运行
复制
class MainActivity : AppCompatActivity() {

    private val TAG = "PLDBINFO"
    lateinit var db: TheDatabase
    lateinit var dao: AllDao
    val songList = listOf<Song>(
        Song(1L,"My Song","x"),
        Song(2L,"Your Song","Y"),
        Song(3L,"Her Song","Z"),
        Song(4L,"His Song","A"),
        Song(5L,"Their Song","B"),
        Song(6L,"Nobody's Song","C")
    )
    val playlistInfoList = listOf<PlaylistInfo>(
        PlaylistInfo("My PlayList"),
        PlaylistInfo("Your PlayList"),
        PlaylistInfo("Her PlayList")
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Get the Database and the Dao
        db = Room.databaseBuilder(this,TheDatabase::class.java,"playlist.db")
            .allowMainThreadQueries()
            .build()
        dao = db.getDao()

        // Add all the Playlist and Songs and add every Song to all the Playlists
        // ONLY IF no data exists
        if (dao.getNumberOfPlaylistInfos() + dao.getNumberOfPlaylistInfos() + dao.getNumberOfSongsInPlaylists() < 1) {
            dao.insertManySongs(songList)
            dao.insertManyPlaylistInfos(playlistInfoList)
            for(p: PlaylistInfo in dao.getAllPlaylistInfos()) {
                for(s: Song in dao.getAllSongs()) {
                    dao.insert(PlaylistSongCrossRef(p.playlistId,s.songId))
                }
            }
        }

        // Write the counts to the Log
        logStats()

        // Extract All Core Objects
        var allPlaylistInfos = dao.getAllPlaylists()
        var allSongs = dao.getAllSongs()
        var allPlaylists = dao.getAllPlaylists()
        var allPlaylistSongCrossRefs = dao.getAllPlaylistSongCrossRefs()
        Log.d(TAG,"Extracted PlaylistInfos = ${allPlaylistInfos.size} " +
                "Extacted Songs = ${allSongs.size} " +
                "Extracted Playlists = ${allPlaylists.size} " +
                "Extracted PlaylistSongCrossRefs = ${allPlaylistSongCrossRefs.size}"
        )


        // Add a new song and also put it into the My PlayList playlist
        dao.insert(PlaylistSongCrossRef(dao.getFirstPlaylistInfoByName("My PlayList").playlistId,dao.insert(Song(10L,"Bert's Song","D"))))
        // ASame as above BUT using function getPlaylistInfoIdByName below that gets the ID
        dao.insert(PlaylistSongCrossRef(getPlaylistInfoIdByName("My PlayList"),dao.insert(Song(20L,"Mary's Song","E"))))

        //
        var otherPlTodelete = dao.getFirstPlaylistInfoByName("Her PlayList")
        for(pl: Playlist in allPlaylistInfos) {
            /* Best to not use this
            if (pl.playlistInfo!!.playlistId == plToDelete.playlistId ) {
                dao.deletePlayListInfoAndSongs(pl.playlistInfo!!,pl.songs!!)
            }

             */
            if (pl.playlistInfo!!.playlistId == otherPlTodelete.playlistId) {
                pl.deletePlayList(dao,pl,false) /* best to only use false */
            }
        }

        var playlistToUpdate = dao.getFirstPlaylistInfoByName("Your PlayList")
        playlistToUpdate.name = "PlayList that is for Your but it was Your PlayList"
        dao.update(playlistToUpdate)

        logStats()
    }

    private fun logStats() {
        Log.d(TAG," Playlist Count = " + dao.getNumberOfPlaylistInfos()
                + " Song Count = " + dao.getNumberOfSongs()
                + " Song/Playlist count = " + dao.getNumberOfSongsInPlaylists()
        )
    }

    private fun getSongIdByName(songName: String): Long {
        return dao.getFirstSongByName(songName).songId
    }
    private fun getPlaylistInfoIdByName(playlistInfoName: String): Long {
        return dao.getFirstPlaylistInfoByName(playlistInfoName).playlistId
    }
}

首先,如果不存在数据(例如通过查询获取行数),则添加3个播放列表和6个歌曲,每个播放列表包含所有歌曲(因此18行交叉引用行)。

  • 显然,这不是真实的情况(坚果,它非常方便/易于测试)

然后,统计数据(每个表的行被输出到日志)。

然后提取所有类型(PlaylistInfo's、Song's、PlaylistSongCrossref和播放列表的),并显示计数(应该与stats相符)。

然后添加两首新歌,不仅作为歌曲,还添加到名为"My PlayList“的PlayList中。

名为“PlayList PlayList”的Playlistinfo (又名PlayList)是根据名称找到的。通过播放列表类中的函数,它与PlayListSongCrossRef一起被删除,因此不会留下孤立的歌曲。

然后,名为"Your PlayList“的播放列表将其命名为”用于您的Playlist,但它是您的PlayList“。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67441934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档