在Java中处理对象关联
在Java中处理对象关联时,分两步骤:1. 查询数据库;2. 做Java中组装对象
对于数据库表
表clazz: id
表student: id, clazzId
在Java中有时需要班级获取班级里的所有学生,是一对多关联
有时学生获取班级信息,是多对一关联
一、一对多关联 OneToMany
将表数据转换为java的运行时数据
类clazz: id, students
类student: id
1.1 从数据库分别查询相关联的实体数据
List fathers = fatherRepo.findSomeList();
List fatherIds = fathers.stream().map(Father::getId).collect(toList);
List children = childRepo.findByFatherIdsIn(fatherIds);
注:oracle的in字句限制1000。MySQL限制了SQL语句的最大长度,可以认为对in语句没有限制。sqlserver对in语句没有限制。
1.2 子表数据挂载到父表对象的属性上
二次查询数据库获取父子表数据后,需要在java代码中,将子表数据挂载到父表对象的属性上。
java代码有三种实现方式:
- 双重for循环
for(father in fathers) {
for(child in children) {
if(child.parentId == father.id) {
faher.children.add(child)
}
}
}
- lamda表达式形式的双重循环
fathers.each(father->{
father.children.addAll(children.stream().filter(c -> c.parentId == father.id).collect())
})
- 借助Map
Map<ID,List<Child>> collect = children.stream().collect(Collectors.groupingBy(Child::getParentId))
fathers.each(father->{
father.children.addAll(collect.getOrDefault(father.id, List.of()))
})
理论上方法3的两次循环时间复杂度为2n,方法1和2的时间复杂度为n^2.
方法2的编码方式最简洁。
方法1的编码方式最灵活,方便增减其他逻辑代码。另外,不存在方法2和3中,有单行代码过长的问题。
二、多对一关联ManyToOne
表clazz: id
表student: id, clazzId
类clazz: id
类student: id, clazz
- 循环使用findById查询数据库
无论是jpa还是MyBatis对findById都有很好的缓存。如下实现即可:
@Transaction(readonly)
List children = childRepo.findSomeChildren()
for(child in children){
Father father = fatherRepo.findById(child.parentId)
child.setFather(father)
}
- 使用findByIdIn避免循环查询数据库
类比子表对象挂载至父表对象的思路,使用findByIdIn。避免循环查询数据库。
由于MyBatis和jpa等框架的缓存,方法1在一般情况下循环查询数据库的次数不会太多。编码实现简单。
方法2避免的循环查询数据库,编码实现比方法1复杂。
优先选择方式2。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律