Android中使用SqlDelight关联两张表的更优实现方案咨询
在SqlDelight中处理关联查询并实现嵌套数据结构的最优方式
在SqlDelight里,你可以通过**自定义映射器(mapper)**来实现主表数据嵌套子表列表的需求,不用再手动处理可空字段的繁琐判断。具体方案如下:
1. 拆分查询逻辑(避免N+1可选)
先分别定义主表和子表的查询语句:
- 主表查询获取Sales部门的员工:
getSalesEmployees: SELECT empId, name FROM EMPLOYEE WHERE dept = 'Sales';
- 子表查询获取指定员工的课程:
getCoursesByEmpId: SELECT courseId, courseName FROM COURSE WHERE empId = ?;
2. 定义目标嵌套数据类
先创建你期望的嵌套结构数据类(以Kotlin为例):
data class EmployeeWithCourses( val empId: String, val name: String, val courses: List<Course> ) data class Course( val courseId: String, val courseName: String )
3. 映射查询结果为嵌套结构
在代码层关联查询结果并组装:
fun getEmployeesWithCourses(): List<EmployeeWithCourses> { val employees = database.getSalesEmployees().executeAsList() return employees.map { emp -> val courses = database.getCoursesByEmpId(emp.empId).executeAsList() .map { Course(it.courseId, it.courseName) } EmployeeWithCourses(emp.empId, emp.name, courses) } }
进阶:单次查询后分组(减少数据库交互)
如果不想执行N+1次查询,可通过一次JOIN获取所有数据,再在内存中分组处理:
定义JOIN查询
getSalesEmployeesWithCourses: SELECT e.empId, e.name, c.courseId, c.courseName FROM EMPLOYEE e LEFT JOIN COURSE c ON e.empId = c.empId WHERE e.dept = 'Sales';
内存分组映射
fun getEmployeesWithCourses(): List<EmployeeWithCourses> { val rawResults = database.getSalesEmployeesWithCourses().executeAsList() return rawResults.groupBy { it.empId } .map { (empId, group) -> val baseEmp = group.first() val courses = group.filter { it.courseId != null } .map { Course(it.courseId!!, it.courseName!!) } EmployeeWithCourses(empId, baseEmp.name, courses) } }
两种方案都能避免手动处理大量可空字段,实现你需要的嵌套列表结构,可根据业务场景选择:拆分查询更直观,单次查询分组则减少数据库交互次数。
内容的提问来源于stack exchange,提问作者mk_369
相关产品推荐
相关产品推荐

