【问题标题】:Select 3 entities at once from Room Database with @Relation使用@Relation 从房间数据库中一次选择 3 个实体
【发布时间】:2021-03-27 13:03:33
【问题描述】:

我的应用程序中有一个数据库,其中包含 3 个表服务器、站点、组

@Entity(tableName = "servers")
data class Server(

    @ColumnInfo(name = "server_id")
    var serverId: Long,

    @ColumnInfo(name = "account_id")
    var accountId: Int,

    @ColumnInfo(name = "device_id")
    var deviceId: Int,

    @ColumnInfo(name = "company_id")
    var companyId: Int
   
    .......


@Entity(tableName = "sites")
data class Site(

    @ColumnInfo(name = "server_id")
    var serverId: Long,

    @ColumnInfo(name = "site_id")
    val siteId: Int,

    @ColumnInfo(name = "description", defaultValue = "")
    val description: String

)



@Entity(tableName = "groups")
data class Group(

    @ColumnInfo(name = "server_id")
    val serverId: Long,

    @ColumnInfo(name = "group_id")
    var groupId: Int,

    @ColumnInfo(name = "site_id")
    val siteId: Int,

    @ColumnInfo(name = "description", defaultValue = "")
    val description: String

    ......

所以我们可以看到,每台服务器都有站点,每个站点都有多个组。 现在我制作了一个名为 ServerSiteWithGroup 的 POJO,其中包含一个服务器和另一个 POJO SiteWithGroup

data class ServerSiteWithGroup(
    @Embedded
    val server: Server,

    @Relation(parentColumn = "server_id", entityColumn = "server_id")
    val siteWithGroup: SiteWithGroup
)


data class SiteWithGroup(
    @Embedded
    val group: Group,

    @Relation(parentColumn = "site_id", entityColumn = "site_id")
    val site: Site
)

因此,鉴于我想对 Room 数据库进行一次查询并获取给定 serverId, siteId, groupId 的服务器、站点、组对象

我试过了,但是不行

    @Transaction
    @Query("Select * from groups 
        inner join servers on groups.server_id = servers.server_id 
        where groups.server_id = :serverId 
        and groups.site_id = :siteId 
        and groups.group_id = :groupId")
    fun getSiteWithGroup(serverId: Long, siteId: Int, groupId: Int): LiveData<ServerSiteWithGroup>

我该如何解决这个问题?

【问题讨论】:

    标签: kotlin android-room pojo data-class android-embedded-api


    【解决方案1】:

    首先,您似乎没有使用 @PrimaryKey 注释定义任何 PRIMARY 键,这会导致编译错误。

    其次,@Query 不应返回 LiveData&lt;ServerSiteWithGroup&gt;,但应返回 LiveData 的数组,这些数组本身(我相信)是 ServerSiteWithGroup 的数组,因此我认为应该改为 LiveData&lt;List&lt;ServerSiteWithGroup&gt;&gt;

    • 请先试试这个,但请考虑在答案末尾添加的 Even More 部分。 .

    我该如何解决这个问题?

    • 您没有提及/指定实际问题是什么。但是,以下是基于您提供的信息的解决方案。 (但为了方便不使用LiveData

    在 Group 实体中,您拥有 ServerId,这是不必要的,因为作为 Group 父级的站点将 Server 作为其父级。这不是错误,但没有必要。

    虽然理论上不需要,但 id 可以是 Long,因此我始终建议使用 Long 而不是 Int 来表示关系。

    示例 这是一个基于您的代码的工作示例。

    服务器

    @Entity(tableName = "servers")
    data class Server(
    
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "server_id")
        var serverId: Long?,
    
        @ColumnInfo(name = "account_id")
        var accountId: Int,
    
        @ColumnInfo(name = "device_id")
        var deviceId: Int,
    
        @ColumnInfo(name = "company_id")
        var companyId: Int
    )
    
    • Primarykey 已定义。
    • autogenerateLong? 允许生成 id。

    网站

    @Entity(tableName = "sites")
    data class Site(
    
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "site_id")
        val siteId: Long?,
    
        @ColumnInfo(name = "server_id")
        var serverId: Long,
    
        @ColumnInfo(name = "description", defaultValue = "")
        val description: String
    )
    

    @Entity(tableName = "groups")
    data class Group(
    
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "group_id")
        var groupId: Long?,
    
        @ColumnInfo(name = "server_id") //?
        val serverId: Long,
    
        @ColumnInfo(name = "site_id")
        val siteId: Long,
    
        @ColumnInfo(name = "description", defaultValue = "")
        val description: String
    )
    

    Alldao Dao's 允许在各个级别插入和提取,特别是使用 @relationJOIN's。

    interface AllDao {
        @Insert
        fun insertServer(server: Server): Long
        @Insert
        fun insertSite(site: Site): Long
        @Insert
        fun insertGroup(group: Group): Long
        @Query("SELECT * FROM servers")
        fun getAllServers(): List<Server>
        @Query("SELECT * FROM sites")
        fun getAllSites(): List<Site>
        @Query("SELECT * FROM groups")
        fun getAllGroups(): List<Group>
        @Transaction
        @Query("SELECT * FROM sites")
        fun getAllSitesWithGroups(): List<SiteWithGroup>
        @Transaction
        @Query("SELECT * FROM servers")
        fun getAllServersWithSitesWithGroups(): List<ServerWithSiteWithGroup>
        @Transaction
        @Query("SELECT * FROM servers INNER JOIN sites ON servers.server_id = sites.server_id INNER JOIN groups on sites.site_id = groups.site_id")
        fun getAllServersWithSitesWithGroupsUsingJoin(): List<ServerWithSiteWithGroup>
    
        @Transaction
        @Query("Select * from groups " +
                "inner join servers on groups.server_id = servers.server_id " +
                "where groups.server_id = :serverId " +
                "and groups.site_id = :siteId " +
                "and groups.group_id = :groupId")
        fun getSiteWithGroup(serverId: Long, siteId: Int, groupId: Int): List<ServerWithSiteWithGroup>
    }
    
    • 请注意原始查询之前的最后两个 @Query,但存在细微差别(查看结果
    • 请注意,您的查询只返回 List 而不是 LiveData

    SiteWithGroup 组与其父站点的 POJO 关系(一个站点可以有多个组)

    data class SiteWithGroup(
        @Embedded
        var site: Site,
    
        @Relation(entity = Group::class, entityColumn = "site_id", parentColumn = "site_id")
        var groups: List<Group>
    )
    
    • 虽然在这种情况下没有必要,但我更喜欢对实体(类)进行编码

    ServerWithSiteWithGroup

    data class ServerWithSiteWithGroup(
        @Embedded
        var server: Server,
    
        @Relation(entity = Site::class, entityColumn = "server_id",parentColumn = "server_id")
        var siteWithGroup: List<SiteWithGroup>
    )
    
    • 请注意,我使用了与原始名称不同的名称,因为我认为它更能描述底层 POJO。

    MyDatabse 将实体和 Dao(s) 联系起来的 @Database 抽象类(为方便起见仅提供一个)

    @Database(entities = arrayOf(Server::class,Site::class,Group::class),version = 1)
    abstract class MyDatabase: RoomDatabase() {
        abstract fun getAllDao(): AllDao
    }
    

    MainActivity 用于演示/bervity/convenience 在主线程上运行

    class MainActivity : AppCompatActivity() {
        val TAG = "MYDBINFO"
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val db = Room.databaseBuilder(applicationContext,MyDatabase::class.java,"MyDatabase")
                .allowMainThreadQueries()
                .build()
            val allDao = db.getAllDao()
            val s1 = Server(null,1,2,3)
            val s2 = Server(null,4,5,6)
            allDao.insertServer(s1)
            allDao.insertServer(s2)
            val site1 = Site(null,1,"Site1 - Server1")
            val site2 = Site(null,1,"Site2 - Server1")
            val site3 = Site(null,2,"Site3 - Server2")
            val site4 = Site(null,2,"Site4 - Server2")
            val site5 = Site(null,1,"Site5 - Server 1")
            allDao.insertSite(site1)
            allDao.insertSite(site2)
            allDao.insertSite(site3)
            allDao.insertSite(site4)
            allDao.insertSite(site5)
            val g1 = Group(null,1,1,"Group1 - Site1 (impicitly Server 1)")
            val g2 = Group(null,10,1,"Group2!!! - Site1 (impicitly Server 1)") // OOOPS no server with ID 10
            val g2_2 = Group(null,1,1,"Group2_2 - Site1 (impicitly Server 1)")
            val g3 = Group(null,2,2,"Group3 - Site2 (impicitly Server 1)")
            allDao.insertGroup(g1)
            allDao.insertGroup(g2)
            allDao.insertGroup(g2_2)
            allDao.insertGroup(g3)
            val servers = allDao.getAllServers()
            Log.d(TAG,"Server List")
            for (s: Server in servers) {
                Log.d(TAG,"\tServerID = " + s.serverId + " CompanyID =" + s.companyId + " AccountID = " + s.accountId + " DeviceID = " + s.deviceId)
            }
            val sites = allDao.getAllSites()
            Log.d(TAG,"Site List")
            for (si: Site in sites) {
                Log.d(TAG,"\tSiteID = " + si.siteId + " Description = " + si.description + " Server ID = " + si.serverId)
            }
            val groups = allDao.getAllGroups()
            for(g: Group in groups) {
                Log.d(TAG,"\tGroup ID = " + g.groupId + " Description = " + g.description + " ServerID = " + g.serverId + " SiteID = " + g.siteId)
            }
            val sitesWithGroupsList = allDao.getAllSitesWithGroups()
            Log.d(TAG,"Site With Groups List")
            for(swgl: SiteWithGroup in sitesWithGroupsList) {
                Log.d(TAG,"\tSiteID = " + swgl.site.siteId + " ServerID = " + swgl.site.serverId + " Description " + swgl.site.description)
                for(grp: Group in swgl.groups) {
                    Log.d(TAG,"\t\tGroup ID = " + grp.groupId + " SiteID = " + grp.siteId + " Description = " + grp.description + " ServerID = " + grp.serverId)
                }
            }
            Log.d(TAG,"****Servers with Sites with Groups using @Relation")
            val swswg = allDao.getAllServersWithSitesWithGroups()
            for(s: ServerWithSiteWithGroup in swswg) {
                Log.d(TAG,"ServerID is " + s.server.serverId)
                Log.d(TAG,"Sites in Server =" + s.siteWithGroup.size)
                for(swg: SiteWithGroup in s.siteWithGroup) {
                    Log.d(TAG,"\tSite is " + swg.site.description)
                    Log.d(TAG,"\tGroups in Site =" + swg.groups.size)
                    for (g: Group in swg.groups) {
                        Log.d(TAG,"\t\tGroup is " + g.description)
                    }
                }
            }
            Log.d(TAG,"****Servers with Sites with Groups using Joins")
            val swswg2 = allDao.getAllServersWithSitesWithGroupsUsingJoin()
            for(s: ServerWithSiteWithGroup in swswg2) {
                Log.d(TAG,"ServerID is " + s.server.serverId)
                Log.d(TAG,"Sites in Server =" + s.siteWithGroup.size)
                for(swg: SiteWithGroup in s.siteWithGroup) {
                    Log.d(TAG,"\tSite is " + swg.site.description)
                    Log.d(TAG,"\tGroups in Site =" + swg.groups.size)
                    for (g: Group in swg.groups) {
                        Log.d(TAG,"\t\tGroup is " + g.description)
                    }
                }
            }
    
            // ORIGINAL PROBLEM QUERY 
            Log.d(TAG,"****Servers With Sites With Groups using joins and where clauses (problem query)")
            val swswgsel = allDao.getSiteWithGroup(1,1,1)
            for (swswg3: ServerWithSiteWithGroup in swswgsel) {
                Log.d(TAG,"ServerID is " + swswg3.server.serverId)
                Log.d(TAG,"Sites in Server =" + swswg3.siteWithGroup.size)
                for(swg: SiteWithGroup in swswg3.siteWithGroup) {
                    Log.d(TAG,"\tSite is " + swg.site.description)
                    Log.d(TAG,"\tGroups in Site =" + swg.groups.size)
                    for (g: Group in swg.groups) {
                        Log.d(TAG,"\t\tGroup is " + g.description)
                    }
                }
            }
        }
    }
    
    • 以上代码依次流过
    • 通过日志记录可以轻松监控结果。
    • 设计为运行一次(多次运行可能会导致一些混乱)
    • 为方便起见,使用了 LiveData。

    结果最初运行时的日志

    • 您的原始查询位于日志末尾

    :-

    03-28 16:56:24.018 D/MYDBINFO: Server List
    03-28 16:56:24.018 D/MYDBINFO: ServerID = 1 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 16:56:24.018 D/MYDBINFO: ServerID = 2 DeviceID = 5 AccountID = 4 CompanyID = 6
    
    03-28 16:56:24.019 D/MYDBINFO: Site List
    03-28 16:56:24.019 D/MYDBINFO:  SiteID = 1 Description = Site1 - Server1 ServerID = 1
    03-28 16:56:24.019 D/MYDBINFO:  SiteID = 2 Description = Site2 - Server1 ServerID = 1
    03-28 16:56:24.019 D/MYDBINFO:  SiteID = 3 Description = Site3 - Server2 ServerID = 2
    03-28 16:56:24.019 D/MYDBINFO:  SiteID = 4 Description = Site4 - Server2 ServerID = 2
    03-28 16:56:24.019 D/MYDBINFO:  SiteID = 5 Description = Site5 - Server 1 ServerID = 1
    
    03-28 16:56:24.021 D/MYDBINFO: Group List
    03-28 16:56:24.022 D/MYDBINFO:      GroupID = 1 Description = Group1 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.022 D/MYDBINFO:      GroupID = 2 Description = Group2!!! - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 10(May not be correct)
    03-28 16:56:24.022 D/MYDBINFO:      GroupID = 3 Description = Group2_2 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.022 D/MYDBINFO:      GroupID = 4 Description = Group3 - Site2 (impicitly Server 1)Parent SiteID = 2 Parent ServerID = 2(May not be correct)
    
    03-28 16:56:24.024 D/MYDBINFO: Site With Groups List
    03-28 16:56:24.024 D/MYDBINFO:  SiteID = 1 Description = Site1 - Server1 ServerID = 1
    03-28 16:56:24.024 D/MYDBINFO:      GroupID = 1 Description = Group1 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.024 D/MYDBINFO:      GroupID = 2 Description = Group2!!! - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 10(May not be correct)
    03-28 16:56:24.024 D/MYDBINFO:      GroupID = 3 Description = Group2_2 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.024 D/MYDBINFO:  SiteID = 2 Description = Site2 - Server1 ServerID = 1
    03-28 16:56:24.024 D/MYDBINFO:      GroupID = 4 Description = Group3 - Site2 (impicitly Server 1)Parent SiteID = 2 Parent ServerID = 2(May not be correct)
    03-28 16:56:24.024 D/MYDBINFO:  SiteID = 3 Description = Site3 - Server2 ServerID = 2
    03-28 16:56:24.024 D/MYDBINFO:  SiteID = 4 Description = Site4 - Server2 ServerID = 2
    03-28 16:56:24.025 D/MYDBINFO:  SiteID = 5 Description = Site5 - Server 1 ServerID = 1
    
    03-28 16:56:24.025 D/MYDBINFO: ****Servers with Sites with Groups using @Relation
    03-28 16:56:24.027 D/MYDBINFO: ServerID = 1 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 16:56:24.028 D/MYDBINFO: Sites in Server =3
    03-28 16:56:24.028 D/MYDBINFO:  SiteID = 1 Description = Site1 - Server1 ServerID = 1
    03-28 16:56:24.028 D/MYDBINFO:  Groups in Site =3
    03-28 16:56:24.028 D/MYDBINFO:      GroupID = 1 Description = Group1 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.028 D/MYDBINFO:      GroupID = 2 Description = Group2!!! - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 10(May not be correct)
    03-28 16:56:24.028 D/MYDBINFO:      GroupID = 3 Description = Group2_2 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.028 D/MYDBINFO:  SiteID = 2 Description = Site2 - Server1 ServerID = 1
    03-28 16:56:24.028 D/MYDBINFO:  Groups in Site =1
    03-28 16:56:24.028 D/MYDBINFO:      GroupID = 4 Description = Group3 - Site2 (impicitly Server 1)Parent SiteID = 2 Parent ServerID = 2(May not be correct)
    03-28 16:56:24.028 D/MYDBINFO:  SiteID = 5 Description = Site5 - Server 1 ServerID = 1
    03-28 16:56:24.028 D/MYDBINFO:  Groups in Site =0
    03-28 16:56:24.028 D/MYDBINFO: ServerID = 2 DeviceID = 5 AccountID = 4 CompanyID = 6
    03-28 16:56:24.028 D/MYDBINFO: Sites in Server =2
    03-28 16:56:24.028 D/MYDBINFO:  SiteID = 3 Description = Site3 - Server2 ServerID = 2
    03-28 16:56:24.028 D/MYDBINFO:  Groups in Site =0
    03-28 16:56:24.028 D/MYDBINFO:  SiteID = 4 Description = Site4 - Server2 ServerID = 2
    03-28 16:56:24.028 D/MYDBINFO:  Groups in Site =0
    
    03-28 16:56:24.028 D/MYDBINFO: ****Servers with Sites with Groups using Joins
    03-28 16:56:24.029 D/MYDBINFO: ServerID = 1 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 16:56:24.029 D/MYDBINFO: Sites in Server =3
    03-28 16:56:24.029 D/MYDBINFO:  SiteID = 1 Description = Site1 - Server1 ServerID = 1
    03-28 16:56:24.029 D/MYDBINFO:  Groups in Site =3
    03-28 16:56:24.029 D/MYDBINFO:      GroupID = 1 Description = Group1 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.029 D/MYDBINFO:      GroupID = 2 Description = Group2!!! - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 10(May not be correct)
    03-28 16:56:24.029 D/MYDBINFO:      GroupID = 3 Description = Group2_2 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.029 D/MYDBINFO:  SiteID = 2 Description = Site2 - Server1 ServerID = 1
    03-28 16:56:24.029 D/MYDBINFO:  Groups in Site =1
    03-28 16:56:24.029 D/MYDBINFO:      GroupID = 4 Description = Group3 - Site2 (impicitly Server 1)Parent SiteID = 2 Parent ServerID = 2(May not be correct)
    03-28 16:56:24.029 D/MYDBINFO:  SiteID = 5 Description = Site5 - Server 1 ServerID = 1
    03-28 16:56:24.029 D/MYDBINFO:  Groups in Site =0
    03-28 16:56:24.029 D/MYDBINFO: ServerID = 10 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 16:56:24.029 D/MYDBINFO: Sites in Server =0
    03-28 16:56:24.029 D/MYDBINFO: ServerID = 1 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 16:56:24.029 D/MYDBINFO: Sites in Server =3
    03-28 16:56:24.030 D/MYDBINFO:  SiteID = 1 Description = Site1 - Server1 ServerID = 1
    03-28 16:56:24.030 D/MYDBINFO:  Groups in Site =3
    03-28 16:56:24.030 D/MYDBINFO:      GroupID = 1 Description = Group1 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.030 D/MYDBINFO:      GroupID = 2 Description = Group2!!! - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 10(May not be correct)
    03-28 16:56:24.030 D/MYDBINFO:      GroupID = 3 Description = Group2_2 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.030 D/MYDBINFO:  SiteID = 2 Description = Site2 - Server1 ServerID = 1
    03-28 16:56:24.030 D/MYDBINFO:  Groups in Site =1
    03-28 16:56:24.030 D/MYDBINFO:      GroupID = 4 Description = Group3 - Site2 (impicitly Server 1)Parent SiteID = 2 Parent ServerID = 2(May not be correct)
    03-28 16:56:24.030 D/MYDBINFO:  SiteID = 5 Description = Site5 - Server 1 ServerID = 1
    03-28 16:56:24.030 D/MYDBINFO:  Groups in Site =0
    03-28 16:56:24.030 D/MYDBINFO: ServerID = 2 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 16:56:24.030 D/MYDBINFO: Sites in Server =2
    03-28 16:56:24.030 D/MYDBINFO:  SiteID = 3 Description = Site3 - Server2 ServerID = 2
    03-28 16:56:24.030 D/MYDBINFO:  Groups in Site =0
    03-28 16:56:24.030 D/MYDBINFO:  SiteID = 4 Description = Site4 - Server2 ServerID = 2
    03-28 16:56:24.030 D/MYDBINFO:  Groups in Site =0
    
    03-28 16:56:24.030 D/MYDBINFO: ****Servers With Sites With Groups using joins and where claues (problem query)
    03-28 16:56:24.031 D/MYDBINFO: ServerID = 1 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 16:56:24.031 D/MYDBINFO: Sites in Server =3
    03-28 16:56:24.031 D/MYDBINFO:  SiteID = 1 Description = Site1 - Server1 ServerID = 1
    03-28 16:56:24.031 D/MYDBINFO:  Groups in Site = 3
    03-28 16:56:24.031 D/MYDBINFO:      GroupID = 1 Description = Group1 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.031 D/MYDBINFO:      GroupID = 2 Description = Group2!!! - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 10(May not be correct)
    03-28 16:56:24.031 D/MYDBINFO:      GroupID = 3 Description = Group2_2 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.031 D/MYDBINFO:  SiteID = 2 Description = Site2 - Server1 ServerID = 1
    03-28 16:56:24.032 D/MYDBINFO:  Groups in Site = 1
    03-28 16:56:24.032 D/MYDBINFO:      GroupID = 4 Description = Group3 - Site2 (impicitly Server 1)Parent SiteID = 2 Parent ServerID = 2(May not be correct)
    03-28 16:56:24.032 D/MYDBINFO:  SiteID = 5 Description = Site5 - Server 1 ServerID = 1
    03-28 16:56:24.032 D/MYDBINFO:  Groups in Site = 0
    

    额外 您可能希望考虑以下使用看似正确的关系:-

    @Transaction
    @Query("SELECT * FROM servers " +
            "JOIN sites ON sites.server_id = servers.server_id " +
            "JOIN groups ON groups.site_id = sites.site_id " +
            "WHERE servers.server_id = :serverId AND sites.site_id = :siteId AND groups.group_id = :groupId")
    fun getSuggested(serverId: Long, siteId: Long, groupId: Long): List<ServerWithSiteWithGroup>
    

    这实际上对相同的测试用例实现了相同的结果:-

    03-28 16:56:24.032 D/MYDBINFO: ????Servers With Sites With Groups and WHERE clause (suggested)
    03-28 16:56:24.033 D/MYDBINFO: ServerID = 1 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 16:56:24.033 D/MYDBINFO: Sites in Server = 3
    03-28 16:56:24.033 D/MYDBINFO:  SiteID = 1 Description = Site1 - Server1 ServerID = 1
    03-28 16:56:24.033 D/MYDBINFO:  Groups in Site = 3
    03-28 16:56:24.033 D/MYDBINFO:      GroupID = 1 Description = Group1 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.033 D/MYDBINFO:      GroupID = 2 Description = Group2!!! - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 10(May not be correct)
    03-28 16:56:24.033 D/MYDBINFO:      GroupID = 3 Description = Group2_2 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    03-28 16:56:24.033 D/MYDBINFO:  SiteID = 2 Description = Site2 - Server1 ServerID = 1
    03-28 16:56:24.033 D/MYDBINFO:  Groups in Site = 1
    03-28 16:56:24.033 D/MYDBINFO:      GroupID = 4 Description = Group3 - Site2 (impicitly Server 1)Parent SiteID = 2 Parent ServerID = 2(May not be correct)
    03-28 16:56:24.033 D/MYDBINFO:  SiteID = 5 Description = Site5 - Server 1 ServerID = 1
    03-28 16:56:24.033 D/MYDBINFO:  Groups in Site = 0
    

    更多

    在指定所有三个参数时,您可能并不期待结果,而是期待单个服务器/站点/组。如果是这样,那么我相信使用@Relation 不是要走的路。相反,没有关系的 POJO 是要走的路。

    以后面查询中的 SQL 为例:-

    SELECT *,sites.description AS site_description, groups.description AS group_description FROM groups 
        INNER JOIN sites ON sites.site_id = groups.site_id 
        INNER JOIN servers ON servers.server_id = sites.server_id
        WHERE servers.server_id = 1 AND sites.site_id = 1 AND groups.group_id = 1;
    

    使用上述数据(注意sites.description AS site_description, groups.description AS group_description 是为了消除/区分不同表中的相同列名)。

    您可能会期望(当 args 为 1,1,1 时):-

    正如上面的日志,这不是 Room 提供的。

    但是考虑 POJO :-

    class AltServerSiteGroup {
        var server_id: Long = 0
        var device_id: Long = 0
        var account_id: Long = 0
        var company_id: Long = 0
        var site_id: Long = -1
        var site_description: String = ""
        var group_id: Long = -1
        var group_description: String = ""
    }
    
    • 注意,我改为使用 Long 而不是 Int(在 Server 中也是如此)。

    然后考虑道:-

    @Transaction
    @Query("SELECT *, sites.description AS site_description, groups.description AS group_description FROM groups " +
            "INNER JOIN sites ON sites.site_id = groups.site_id " +
            "INNER JOIN servers ON servers.server_id = sites.server_id " +
            "WHERE servers.server_id = :serverId AND sites.site_id = :siteId AND groups.group_id = :groupId")
    fun getAlt(serverId: Long, siteId: Long, groupId: Long): List<AltServerSiteGroup>
    
    • 如果只能返回 1 个值,则可以使用 AltServerSiteGroup 而不是 List&lt;AltServerSiteGroup&gt;(如果 ID 是主键,则会出现这种情况)。

    所以通过将以下内容添加到 MainActivity :-

       Log.d(TAG, "Alternative Perhaps what is wanted")
        val alt = allDao.getAlt(1,1,1)
        for(s: AltServerSiteGroup in alt) {
            logserver(Server(s.server_id,s.account_id,s.device_id,s.company_id))
            logsite(Site(s.site_id,s.server_id,s.site_description))
            loggroup(Group(s.group_id,s.server_id,s.site_id,s.group_description))
        }
    
    • 添加了记录实体和日志服务器(服务器(....))等的函数

    那么该部分的结果将是:-

    03-28 19:10:41.930 D/MYDBINFO: Alternative Perhaps what is wanted
    03-28 19:10:41.931 D/MYDBINFO: ServerID = 1 DeviceID = 2 AccountID = 1 CompanyID = 3
    03-28 19:10:41.931 D/MYDBINFO:  SiteID = 1 Description = Site1 - Server1 ServerID = 1
    03-28 19:10:41.931 D/MYDBINFO:      GroupID = 1 Description = Group1 - Site1 (impicitly Server 1)Parent SiteID = 1 Parent ServerID = 1(May not be correct)
    

    即与选择标准匹配的单个服务器/站点/组。

    您可以向 AltServerSiteGroup 添加函数以返回提取的服务器/站点/组对象,但请注意,这些对象与完整/完整对象不同,因为它们只有单个服务器站点组,例如:-

    class AltServerSiteGroup {
        var server_id: Long = 0
        var device_id: Long = 0
        var account_id: Long = 0
        var company_id: Long = 0
        var site_id: Long = -1
        var site_description: String = ""
        var group_id: Long = -1
        var group_description: String = ""
    
        fun getServer(): Server {
            return Server(server_id,account_id,device_id,company_id)
        }
    
        fun getSite(): Site {
            return Site(site_id,server_id,site_description)
        }
    
        fun getGroup(): Group {
            return Group(group_id,server_id,site_id,group_description)
        }
    }
    
    • 说明

    • 简而言之,Room 将根据@Relation 构建完整 对象,从而添加额外的不需要的 站点和组。

    • 如果您查看 Java(生成)中 Dao 的代码(使用项目窗口中的 Android 视图),请注意文件名后缀为 _Impl (因此对于 AllDao,如使用上面,在生成的java中它是AllDao_Impl),你会看到房间做了什么,并且为getAlt构建的代码比getSiteWithGroup的代码短很多。

    【讨论】:

    • 这似乎是一个非常具有分析性的答案,我肯定会去研究它。提前感谢您分享您的知识。当我发现什么更适合我的需求时,我会回来的!
    • 迈克...我不明白。在上一个查询“allDao.getSiteWithGroup(1,1,1)”中,由于要求提供特定的siteId和groupId,我们可以清楚地看到在ForLoop中您LOG多个站点。我们不想要那个..
    • @james04 参见底部的 Even More,查询 getAlt(1,1,1) 通过 POJO AltServerSiteGroup 仅返回 1 个服务器站点组t 使用 @Relation,但只有所需列的成员(变量)。
    • 是的,我知道这个解决方案。然而,重点是使用 @Relation 和 3 个实体来做到这一点。我在 Google 上的 IssueTracker 上发布了类似的问题,他们还说无法完成!
    • @james04 from developer.android.com/reference/androidx/room/Relation 可以在 POJO 中用于自动获取关系实体的便利注解。当查询返回 POJO 时,它的所有关系也由 Room 获取。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多