下面是Android文档中的多到多关系,请在这里找到:定义多到多的关系。
我有以下实体
@Entity
class Song(
@PrimaryKey val songId: Long,
@ColumnInfo val name: String,
@ColumnInfo val path: Uri,
)@Entity
data class PlaylistInfo(
@ColumnInfo var name: String,
@PrimaryKey(autoGenerate = true) val playlistId: Long = 0,
)然后,我有一个实体,是两者之间的交叉参照。
@Entity(primaryKeys = ["playlistId", "songId"])
data class PlaylistSongCrossRef(
val playlistId: Long,
val songId: Long
)最后,我有一个类,它使用PlaylistSongCrossRef作为连接将两者结合在一起。
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播放列表
我不知道从这里往哪里走。如果有人能向我推荐一种资源,可以帮助我解决问题,或者给出一个可行的实现,那将是非常感谢的。
发布于 2021-05-08 15:22:42
我现在想弄清楚如何插入、更新或删除播放列表
播放列表是一个POJO,用于从数据库中提取数据,而不是修改数据库中的数据。也就是说,这是单向的。
但是,如果它不是一个数据类,而是一个类(我认为),那么您可以添加函数来执行这些操作。例如:
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!!)
}
}
}
}你所能做的,用一个提取的播放列表是说删除播放列表和歌曲,如:-
@Delete()
fun deletePlayListInfoAndSongs(playlistInfo: PlaylistInfo, songs: List<Song>): Int但是,be 警告,上面的不会删除关联的PlaylistSongCrossRef行,因此最终会出现孤儿,这可能会有问题。
您可能希望考虑定义外键,并使用onDelete和/或onUpdate操作来级联删除。
Example/Demo
下面是一个基于实体的示例(为方便起见,歌曲路径改为字符串而不是URI )和上面的Playlist类。
刀供您考虑:-
@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)
}在显示更新、删除和插入示例的活动中,可能需要考虑以下几点:
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“。
https://stackoverflow.com/questions/67441934
复制相似问题