业务场景:
采集服务持续采集数据并放入容器中,每当容器的数量大于1000时,会将容器内的数据放入缓存容器,并清空容器,执行一次保存缓存容器的操作,保存结束后清空缓存数据。
报错场景:
在保存这1000条缓存容器的数据时候偶尔会报More than one row with the given identifier was found…的错误
一般情况这个错误:More than one row with the given identifier was found…..都是查询的时候发生,这次发现在保存时任然也会出现这样的错误。接下来写了一个test代码:
@Component
public class ThreadTest2 {
CollectDataDao collectDataDao;
@Autowired
public void setCollectDataDao(CollectDataDao collectDataDao) {
this.collectDataDao = collectDataDao;
}
public void testSaveAll() throws InterruptedException {
List<CollectData> collectDataList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
CollectData collectData = new CollectData();
collectData.setApmac("123");
collectData.setMac("321");
collectData.setCreatedTime(new Date());
collectData.setDate(new Date());
collectData.setStatus(i);
collectDataList.add(collectData);
}
for (int j = 0; j < 10; j++) {
try {
CollectData save = collectDataDao.save(collectDataList.get(0));
CollectData save1 = collectDataDao.save(collectDataList.get(1));
CollectData save2 = collectDataDao.save(collectDataList.get(2));
CollectData save3 = collectDataDao.save(collectDataList.get(0));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
当程序save3时就会报这样的错误,通过debugger发现通过save方法(这里主键id是自增)原对象会被填充自生成的id,当再一次被保存时就会产生上面的异常。
我们知道使用jpa时,有id的会被执行更新操作,而这里是报错,同过查看源码可以看到
jpa在保存的时候会判断是否是一个新的对象,如果是一个新的对象,并且存在id才会执行更新操作。
结论:
jpa在保存的时候如果对同一个对象保存多次就会报More than one row with the given identifier was found的异常。
回到项目的问题,在批量保存的时候报的这个错误的原因通过分析可以知道,如果容器的数量到达1000时容器里的数据就会放到缓存容器,原容器被清空,在保存缓存容器数据还没保存结束,容器又达到1000,此时容器又会将数据放入缓存容器中并再保存,导致缓存容器存在2000条数据并有一些已经保存,最后造成了异常。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/5350.html