You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Room中如何让Machine实体关联并包含MachineType实体?

Hey there! I totally get where you're coming from—you’re used to Spring Boot’s JPA letting you directly embed a related entity via foreign keys, but Room’s behaving differently and it’s frustrating. Let’s walk through exactly how to replicate that "direct entity reference" behavior in Room.

1. First, Update Your Entities with Proper Foreign Key Setup

First, we need to add a foreign key column to the Machine entity that links to MachineType. This tells SQLite how the two tables are related, but alone it won’t let you fetch the full MachineType with Machine—we’ll fix that next.

@Entity(
    foreignKeys = [ForeignKey(
        entity = MachineType::class,
        parentColumns = ["id"],
        childColumns = ["machine_type_id"],
        onDelete = ForeignKey.CASCADE // Optional: defines behavior if MachineType is deleted
    )]
)
data class Machine(
    @PrimaryKey val id: Long,
    val machine_type_id: Long // Foreign key linking to MachineType's id
)

@Entity
data class MachineType(
    @PrimaryKey val id: Long
    // Add any other fields you need here, e.g., name, description
)
2. Create a Combined Data Class for Joined Results

Room doesn’t let you directly nest entities in each other like JPA does. Instead, we’ll make a separate data class that wraps both Machine and its associated MachineType using Room’s @Embedded and @Relation annotations.

data class MachineWithType(
    @Embedded val machine: Machine, // Pulls all fields from Machine into this class
    @Relation(
        parentColumn = "machine_type_id", // Foreign key in Machine
        entityColumn = "id" // Primary key in MachineType
    )
    val machineType: MachineType // The related MachineType entity
)
3. Modify Your DAO to Fetch the Combined Data

Next, update your DAO to return this combined data class. We use @Transaction because Room needs to run two queries (one for Machine, one for the matching MachineType) in a single transaction to keep data consistent.

@Dao
interface MachineDao {
    // Fetch a single machine with its associated type
    @Transaction
    @Query("SELECT * FROM Machine WHERE id = :machineId")
    suspend fun getMachineWithType(machineId: Long): MachineWithType?

    // Fetch all machines along with their types
    @Transaction
    @Query("SELECT * FROM Machine")
    suspend fun getAllMachinesWithTypes(): List<MachineWithType>
}
4. Use This in Your REST Endpoints

Now when you fetch data from the DAO, you’ll get a MachineWithType object that contains both the Machine and its full MachineType—exactly like the behavior you’re used to in Spring Boot. Here’s a quick example of how to use this in a REST controller:

@RestController
@RequestMapping("/machines")
class MachineController(
    private val machineDao: MachineDao
) {
    @GetMapping("/{id}")
    suspend fun getMachine(@PathVariable id: Long): ResponseEntity<MachineWithType> {
        val machineWithType = machineDao.getMachineWithType(id)
        return machineWithType?.let { ResponseEntity.ok(it) } 
            ?: ResponseEntity.notFound().build()
    }
}
A Quick Note on Why Foreign Keys Alone Aren’t Enough

Room is a lightweight SQLite-based ORM, unlike JPA which handles automatic lazy-loading and entity embedding out of the box. The foreign key only defines the database-level relationship—you need @Relation to tell Room how to fetch and map the related entity alongside the parent.

内容的提问来源于stack exchange,提问作者jared

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:34:31