为什么会遇到这个问题
在Java的开发过程中,会遇到一些复制对象,复制数据的情况,或者遇到基于旧的对象的值,赋予新的值的循环操作,就会出现遍历赋值出来的对象列表内的对象值完全是一样的,甚至都是最后一个对象的值。
错误的代码示例
ProjectEntity projectEntity = this.selectById(id);
List<ProjectEntity> projectEntities = new ArrayList<>();
userIds.forEach(item->{
projectEntity.setCreateBy(item);
projectEntities.add(projectEntity);
});
this.insertBatch(projectEntities);
从以上的代码简单来看
第一步:从数据库根据id查找到一个基础对象值
第二步:遍历循环,依次修改对象的createBy字段内容,并且将第一个数据写入列表的第一个元素内…第二个数据写入第二个元素内…依次类推
第三步:结束循环,使用遍历操作的形式插入数据库
结果:插入数据库的数据都是一模一样的,并且都是最后一个对象的值
原因解析
因为在放在for循环之前只是指定了一个内存地址,每次都在一个内存地址上覆盖原来的数据,所以你得到的永远是循环最后一次的值。
换句话说,在循环内操作的只是一次引用,并不是我们所理解的“值”
解决方法
1、在循环体内,每次循环都应该先初始化一个新的对象,也就是说new一遍对象,让其获取新的地址
userIds.forEach(item->{
ProjectEntity projectEntity = new ProjectEntity();
projectEntity.setCreateBy(item);
projectEntities.add(projectEntity);
});
this.insertBatch(projectEntities);
这个方法是正确的,但是我认为只是简单的解决了问题,但没有解决需求。
实际上我们更希望的是,能够保留从数据库中获取到的对象的数据,并且在其基础上对数据进行修改,最后插入N条新的数据到数据库中
参考答案
//根据id获取方案基本信息
ProjectEntity projectEntity = this.selectById(id);
List<ProjectEntity> projectEntities = new ArrayList<>();
userIds.forEach(item->{
//初始化新的对象引用 使用hutool的实体内容复制
ProjectEntity newProjectEntity= Convert.convert(ProjectEntity.class,projectEntity);
newProjectEntity.setCreateBy(item);
projectEntities.add(newProjectEntity);
});
this.insertBatch(projectEntities);