含OneToMany与ManyToMany关联的Parent实体查询返回重复Child问题
Parent查询出现重复Child的原因分析
核心原因
该现象由多关联查询产生的笛卡尔积,结合Child实体未正确实现equals()和hashCode()方法共同导致。
具体拆解
笛卡尔积导致结果集行数倍增
当JPA查询Parent并同时加载其addresses(OneToMany)和children(ManyToMany)关联时,会生成多表连接的SQL语句:将Parent与Address左连接,再与Person_Child_Mapping中间表、Child表左连接。
若当前Parent关联了2个Address、3个Child,查询结果集的行数会是2*3=6——每一个Address都会与每一个Child组合生成一行数据。Set集合去重机制失效
children属性声明为Set<Child>,Set的去重逻辑完全依赖元素的equals()和hashCode()方法。
如果Child类没有重写这两个方法,会默认使用Object类的实现:基于对象内存地址判断是否相等。在笛卡尔积的结果集中,每一行数据都会生成一个新的Child实例(即使对应数据库中同一条记录),这些实例的内存地址不同,Set会将它们判定为不同对象,最终导致集合中出现6个重复的Child对象。List无去重逻辑,显示正常
addresses是List<Address>,List本身允许重复元素,会直接将结果集中的2个Address实例存入集合,因此你看到的addresses数量符合预期。
内容的提问来源于stack exchange,提问作者Akshay Salvi
相关产品推荐
相关产品推荐

