Kotlin Room 一对多关系如何按 SQL 排序?
Kotlin Room one to many relationship how to order by SQL?
我有两个 @Entity
:
User.kt
@Entity
data class User(
@PrimaryKey val userId: Long,
val name: String,
val age: Int
)
Playlist.kt
@Entity
data class Playlist(
val userCreatorId: Long,
val playlistName: String,
@ColumnInfo(name = "created_at") val createdAt: Long
) {
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "play_list_id") var playlistId: Long = 0
}
通过 @Relation
添加了一对多关系
data class UserWithPlaylists(
@Embedded val user: User,
@Relation(
parentColumn = "userId",
entityColumn = "userCreatorId"
)
val playlists: List<Playlist>
)
然后在道中:
@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylists(): List<UserWithPlaylists>
一切正常,但如何按 createAt
对 UserWithPlaylists
进行排序?
fun getUsersWithPlaylists(): List<UserWithPlaylists>
的默认顺序是什么?我知道对结果 List<UserWithPlaylists>
sortedByDescending
或 sortedBy
进行排序是可行的。 SQL如何在Dao层实现?
谢谢。
What's the default order of the fun getUsersWithPlaylists(): List.
我认为是按主键升序排列的。
How to achieve in Dao layer by SQL?
使用@Relation 你不能。 @Relation 调用检索相关项的基础查询。
但是,您可以通过查询提取父项,然后调用您自己的子查询来获取子项,从而绕过@Relation。
这是一个绕过 @Relation 的简单示例,允许播放列表按播放列表名称排序,然后是 created_at 和 4 个排列。
请注意,使用抽象 class 而不是接口,从而允许使用非抽象函数。
道 (allDao):-
@Dao
abstract class AllDao {
@Insert
abstract fun insert(user: User): Long
@Insert
abstract fun insert(playlist: Playlist): Long
@Query("SELECT * FROM playlist WHERE userCreatorId=:userCreatorId ORDER BY playlistName ASC, created_at ASC")
abstract fun getPlayListsAscendingCreateAtAscending(userCreatorId: Long): List<Playlist>
@Query("SELECT * FROM playlist WHERE userCreatorId=:userCreatorId ORDER BY playlistName DESC, created_at ASC")
abstract fun getPlayListsDescendingCreatedAtAscending(userCreatorId: Long): List<Playlist>
@Query("SELECT * FROM playlist WHERE userCreatorId=:userCreatorId ORDER BY playlistName ASC, created_at DESC")
abstract fun getPlayListsAscendingCreatedAtDescending(userCreatorId: Long): List<Playlist>
@Query("SELECT * FROM playlist WHERE userCreatorId=:userCreatorId ORDER BY playlistName DESC, created_at DESC")
abstract fun getPlayListsDescendingCreatedAtDescending(userCreatorId: Long): List<Playlist>
@Transaction
@Query("")
fun getPlaylistWithSortedUsers(sortPlayListAscending: Boolean, sortCreatedByAscending: Boolean): List<UserWithPlaylists> {
val rv: ArrayList<UserWithPlaylists> = arrayListOf()
val userList = getUserList()
for (u: User in userList) {
if (sortPlayListAscending && sortCreatedByAscending) {
rv.add(UserWithPlaylists(u,getPlayListsAscendingCreateAtAscending(u.userId!!)))
}
if (!sortPlayListAscending && sortCreatedByAscending){
rv.add(UserWithPlaylists(u,getPlayListsDescendingCreatedAtAscending(u.userId!!)))
}
if (sortPlayListAscending && ! sortCreatedByAscending) {
rv.add(UserWithPlaylists(u,getPlayListsAscendingCreatedAtDescending(u.userId!!)))
}
if (!sortPlayListAscending && !sortCreatedByAscending) {
rv.add(UserWithPlaylists(u,getPlayListsDescendingCreatedAtDescending(u.userId!!)))
}
}
return rv
}
}
- 请注意,这通过利用 4 个简单的基础查询,避免了使用包含 CASE WHEN THEN ELSE END 构造的单个查询来应用排序顺序的复杂性。
- 虚拟@Query("") 只是为了允许@Transaction 注解
工作Example/Demo
下面是上面的演示:-
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val user1Id = dao.insert(User(name = "User1", age = 20))
val user2Id = dao.insert(User(name = "Fred", age = 19))
val user3Id = dao.insert(User(name = "Mary", age = 21))
dao.insert(playlist = Playlist(user1Id,"M",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"N",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"A",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"Z",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"B",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"B",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"B",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"1",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"2",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"3",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"9",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"8",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"3",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"3",System.currentTimeMillis()))
for(u: UserWithPlaylists in dao.getPlaylistWithSortedUsers(true,false)) {
Log.d("DBINFO","User is ${u.user.name}")
for(p: Playlist in u.playlists) {
Log.d("DBINFO","\tPlaylist is ${p.playlistName} crtd ${p.createdAt}")
}
}
for(u: UserWithPlaylists in dao.getPlaylistWithSortedUsers(false,true)) {
Log.d("DBINFO","User is ${u.user.name}")
for(p: Playlist in u.playlists) {
Log.d("DBINFO","\tPlaylist is ${p.playlistName} crtd ${p.createdAt}")
}
}
这导致日志中出现以下内容:-
2021-11-25 09:20:34.717 D/DBINFO: User is User1
2021-11-25 09:20:34.717 D/DBINFO: Playlist is A crtd 1637792434681
2021-11-25 09:20:34.717 D/DBINFO: Playlist is B crtd 1637792434694
2021-11-25 09:20:34.717 D/DBINFO: Playlist is B crtd 1637792434692
2021-11-25 09:20:34.718 D/DBINFO: Playlist is B crtd 1637792434687
2021-11-25 09:20:34.718 D/DBINFO: Playlist is M crtd 1637792434678
2021-11-25 09:20:34.718 D/DBINFO: Playlist is N crtd 1637792434680
2021-11-25 09:20:34.718 D/DBINFO: Playlist is Z crtd 1637792434684
2021-11-25 09:20:34.718 D/DBINFO: User is Fred
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 1 crtd 1637792434695
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 2 crtd 1637792434697
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 3 crtd 1637792434707
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 3 crtd 1637792434705
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 3 crtd 1637792434698
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 8 crtd 1637792434703
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 9 crtd 1637792434701
2021-11-25 09:20:34.718 D/DBINFO: User is Mary
2021-11-25 09:20:34.723 D/DBINFO: User is User1
2021-11-25 09:20:34.723 D/DBINFO: Playlist is Z crtd 1637792434684
2021-11-25 09:20:34.723 D/DBINFO: Playlist is N crtd 1637792434680
2021-11-25 09:20:34.723 D/DBINFO: Playlist is M crtd 1637792434678
2021-11-25 09:20:34.723 D/DBINFO: Playlist is B crtd 1637792434687
2021-11-25 09:20:34.723 D/DBINFO: Playlist is B crtd 1637792434692
2021-11-25 09:20:34.723 D/DBINFO: Playlist is B crtd 1637792434694
2021-11-25 09:20:34.723 D/DBINFO: Playlist is A crtd 1637792434681
2021-11-25 09:20:34.723 D/DBINFO: User is Fred
2021-11-25 09:20:34.723 D/DBINFO: Playlist is 9 crtd 1637792434701
2021-11-25 09:20:34.723 D/DBINFO: Playlist is 8 crtd 1637792434703
2021-11-25 09:20:34.723 D/DBINFO: Playlist is 3 crtd 1637792434698
2021-11-25 09:20:34.724 D/DBINFO: Playlist is 3 crtd 1637792434705
2021-11-25 09:20:34.724 D/DBINFO: Playlist is 3 crtd 1637792434707
2021-11-25 09:20:34.724 D/DBINFO: Playlist is 2 crtd 1637792434697
2021-11-25 09:20:34.724 D/DBINFO: Playlist is 1 crtd 1637792434695
2021-11-25 09:20:34.724 D/DBINFO: User is Mary
我有两个 @Entity
:
User.kt
@Entity
data class User(
@PrimaryKey val userId: Long,
val name: String,
val age: Int
)
Playlist.kt
@Entity
data class Playlist(
val userCreatorId: Long,
val playlistName: String,
@ColumnInfo(name = "created_at") val createdAt: Long
) {
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "play_list_id") var playlistId: Long = 0
}
通过 @Relation
data class UserWithPlaylists(
@Embedded val user: User,
@Relation(
parentColumn = "userId",
entityColumn = "userCreatorId"
)
val playlists: List<Playlist>
)
然后在道中:
@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylists(): List<UserWithPlaylists>
一切正常,但如何按 createAt
对 UserWithPlaylists
进行排序?
fun getUsersWithPlaylists(): List<UserWithPlaylists>
的默认顺序是什么?我知道对结果 List<UserWithPlaylists>
sortedByDescending
或 sortedBy
进行排序是可行的。 SQL如何在Dao层实现?
谢谢。
What's the default order of the fun getUsersWithPlaylists(): List.
我认为是按主键升序排列的。
How to achieve in Dao layer by SQL?
使用@Relation 你不能。 @Relation 调用检索相关项的基础查询。
但是,您可以通过查询提取父项,然后调用您自己的子查询来获取子项,从而绕过@Relation。
这是一个绕过 @Relation 的简单示例,允许播放列表按播放列表名称排序,然后是 created_at 和 4 个排列。
请注意,使用抽象 class 而不是接口,从而允许使用非抽象函数。
道 (allDao):-
@Dao
abstract class AllDao {
@Insert
abstract fun insert(user: User): Long
@Insert
abstract fun insert(playlist: Playlist): Long
@Query("SELECT * FROM playlist WHERE userCreatorId=:userCreatorId ORDER BY playlistName ASC, created_at ASC")
abstract fun getPlayListsAscendingCreateAtAscending(userCreatorId: Long): List<Playlist>
@Query("SELECT * FROM playlist WHERE userCreatorId=:userCreatorId ORDER BY playlistName DESC, created_at ASC")
abstract fun getPlayListsDescendingCreatedAtAscending(userCreatorId: Long): List<Playlist>
@Query("SELECT * FROM playlist WHERE userCreatorId=:userCreatorId ORDER BY playlistName ASC, created_at DESC")
abstract fun getPlayListsAscendingCreatedAtDescending(userCreatorId: Long): List<Playlist>
@Query("SELECT * FROM playlist WHERE userCreatorId=:userCreatorId ORDER BY playlistName DESC, created_at DESC")
abstract fun getPlayListsDescendingCreatedAtDescending(userCreatorId: Long): List<Playlist>
@Transaction
@Query("")
fun getPlaylistWithSortedUsers(sortPlayListAscending: Boolean, sortCreatedByAscending: Boolean): List<UserWithPlaylists> {
val rv: ArrayList<UserWithPlaylists> = arrayListOf()
val userList = getUserList()
for (u: User in userList) {
if (sortPlayListAscending && sortCreatedByAscending) {
rv.add(UserWithPlaylists(u,getPlayListsAscendingCreateAtAscending(u.userId!!)))
}
if (!sortPlayListAscending && sortCreatedByAscending){
rv.add(UserWithPlaylists(u,getPlayListsDescendingCreatedAtAscending(u.userId!!)))
}
if (sortPlayListAscending && ! sortCreatedByAscending) {
rv.add(UserWithPlaylists(u,getPlayListsAscendingCreatedAtDescending(u.userId!!)))
}
if (!sortPlayListAscending && !sortCreatedByAscending) {
rv.add(UserWithPlaylists(u,getPlayListsDescendingCreatedAtDescending(u.userId!!)))
}
}
return rv
}
}
- 请注意,这通过利用 4 个简单的基础查询,避免了使用包含 CASE WHEN THEN ELSE END 构造的单个查询来应用排序顺序的复杂性。
- 虚拟@Query("") 只是为了允许@Transaction 注解
工作Example/Demo
下面是上面的演示:-
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
val user1Id = dao.insert(User(name = "User1", age = 20))
val user2Id = dao.insert(User(name = "Fred", age = 19))
val user3Id = dao.insert(User(name = "Mary", age = 21))
dao.insert(playlist = Playlist(user1Id,"M",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"N",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"A",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"Z",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"B",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"B",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user1Id,"B",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"1",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"2",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"3",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"9",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"8",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"3",System.currentTimeMillis()))
dao.insert(playlist = Playlist(user2Id,"3",System.currentTimeMillis()))
for(u: UserWithPlaylists in dao.getPlaylistWithSortedUsers(true,false)) {
Log.d("DBINFO","User is ${u.user.name}")
for(p: Playlist in u.playlists) {
Log.d("DBINFO","\tPlaylist is ${p.playlistName} crtd ${p.createdAt}")
}
}
for(u: UserWithPlaylists in dao.getPlaylistWithSortedUsers(false,true)) {
Log.d("DBINFO","User is ${u.user.name}")
for(p: Playlist in u.playlists) {
Log.d("DBINFO","\tPlaylist is ${p.playlistName} crtd ${p.createdAt}")
}
}
这导致日志中出现以下内容:-
2021-11-25 09:20:34.717 D/DBINFO: User is User1
2021-11-25 09:20:34.717 D/DBINFO: Playlist is A crtd 1637792434681
2021-11-25 09:20:34.717 D/DBINFO: Playlist is B crtd 1637792434694
2021-11-25 09:20:34.717 D/DBINFO: Playlist is B crtd 1637792434692
2021-11-25 09:20:34.718 D/DBINFO: Playlist is B crtd 1637792434687
2021-11-25 09:20:34.718 D/DBINFO: Playlist is M crtd 1637792434678
2021-11-25 09:20:34.718 D/DBINFO: Playlist is N crtd 1637792434680
2021-11-25 09:20:34.718 D/DBINFO: Playlist is Z crtd 1637792434684
2021-11-25 09:20:34.718 D/DBINFO: User is Fred
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 1 crtd 1637792434695
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 2 crtd 1637792434697
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 3 crtd 1637792434707
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 3 crtd 1637792434705
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 3 crtd 1637792434698
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 8 crtd 1637792434703
2021-11-25 09:20:34.718 D/DBINFO: Playlist is 9 crtd 1637792434701
2021-11-25 09:20:34.718 D/DBINFO: User is Mary
2021-11-25 09:20:34.723 D/DBINFO: User is User1
2021-11-25 09:20:34.723 D/DBINFO: Playlist is Z crtd 1637792434684
2021-11-25 09:20:34.723 D/DBINFO: Playlist is N crtd 1637792434680
2021-11-25 09:20:34.723 D/DBINFO: Playlist is M crtd 1637792434678
2021-11-25 09:20:34.723 D/DBINFO: Playlist is B crtd 1637792434687
2021-11-25 09:20:34.723 D/DBINFO: Playlist is B crtd 1637792434692
2021-11-25 09:20:34.723 D/DBINFO: Playlist is B crtd 1637792434694
2021-11-25 09:20:34.723 D/DBINFO: Playlist is A crtd 1637792434681
2021-11-25 09:20:34.723 D/DBINFO: User is Fred
2021-11-25 09:20:34.723 D/DBINFO: Playlist is 9 crtd 1637792434701
2021-11-25 09:20:34.723 D/DBINFO: Playlist is 8 crtd 1637792434703
2021-11-25 09:20:34.723 D/DBINFO: Playlist is 3 crtd 1637792434698
2021-11-25 09:20:34.724 D/DBINFO: Playlist is 3 crtd 1637792434705
2021-11-25 09:20:34.724 D/DBINFO: Playlist is 3 crtd 1637792434707
2021-11-25 09:20:34.724 D/DBINFO: Playlist is 2 crtd 1637792434697
2021-11-25 09:20:34.724 D/DBINFO: Playlist is 1 crtd 1637792434695
2021-11-25 09:20:34.724 D/DBINFO: User is Mary