ROOM存储含自引用Node类的Tree实体遇栈溢出,求助
问题原因
你遇到的栈溢出是因为Node类的循环引用导致序列化无限递归:每个Node持有parent引用,父Node又持有left/right子Node引用,当Room(底层用Gson序列化嵌套对象)尝试存储Tree时,会不断递归序列化父节点和子节点,直到栈空间耗尽。
解决方案
方案1:采用关系型数据库设计(推荐)
数据库不适合直接存储嵌套对象,正确的做法是把Node单独作为实体,用ID关联父子节点,Tree只存储根节点的ID:
修改实体类
@Entity(tableName = "trees") data class Tree( @PrimaryKey(autoGenerate = true) val id: Int = 0, // 存储根节点的ID,而非整个Node对象 val rootNodeId: Int? = null ) @Entity( tableName = "nodes", foreignKeys = [ForeignKey( entity = Node::class, parentColumns = ["id"], childColumns = ["parentId"], // 删除父节点时自动删除子节点,可根据需求调整 onDelete = ForeignKey.CASCADE )] ) @Parcelize data class Node( @PrimaryKey(autoGenerate = true) val id: Int = 0, // 存储左/右子节点的ID var leftNodeId: Int? = null, var rightNodeId: Int? = null, var isRoot: Boolean = false, var isLeft: Boolean? = null, var isRight: Boolean? = null, var hash: Int = 0, // 存储父节点的ID var parentId: Int? = null ) : Parcelable
构建树形结构
从数据库读取时,先查询根节点,再递归查询子节点来构建完整树形:
// Dao示例 @Dao interface NodeDao { @Query("SELECT * FROM nodes WHERE id = :nodeId") suspend fun getNodeById(nodeId: Int): Node? @Query("SELECT * FROM nodes WHERE parentId = :parentId") suspend fun getChildrenByParentId(parentId: Int): List<Node> } // 构建树形的函数示例 suspend fun buildTree(rootNodeId: Int?, nodeDao: NodeDao): Node? { rootNodeId ?: return null val root = nodeDao.getNodeById(rootNodeId) ?: return null val children = nodeDao.getChildrenByParentId(root.id) children.forEach { child -> val childTree = buildTree(child.id, nodeDao) if (child.isLeft == true) { root.left = childTree } else if (child.isRight == true) { root.right = childTree } childTree?.parent = root } return root }
方案2:忽略循环引用(不推荐,仅临时解决)
如果非要在Tree中存储完整Node对象,可以通过Gson注解忽略parent字段的序列化,避免递归:
@Parcelize class Node( // 序列化时忽略parent字段,打破循环 @JsonIgnore var parent: Node? = null, var left: Node? = null, var right: Node? = null, var isRoot: Boolean = false, var isLeft: Boolean? = null, var isRight: Boolean? = null, var hash: Int = 0, ) : Parcelable
⚠️ 注意:这种方式读取数据后,parent字段会为null,需要手动重新关联,维护成本高,不适合长期使用。
内容的提问来源于stack exchange,提问作者Denterrr
相关产品推荐
相关产品推荐

